Manual of Fun Programming Language

0. What is Fun?

Fun is a simple, structured, imperative, dynamic, object-oriented, functional and high-level programming language. Fun was developed by Wisdom Cheung in 2010 as a scripting language to reuse resources of Pascal. Fun's syntax is simple and clear, it comes from Ada and was changed for easy to use and input. Fun's exception handling syntax is similar to Delphi. Fun is dynamic typing and supports type conversions automatically when needed. Fun supports class-based object-oriented programming. Fun supports first-class functions functional programming, looks like Lisp and Javascript. Fun implements a simple and lightweight reference counting garbage collector. Fun's regular expressions handling is Perl-Compatible. Fun provides simple and powerful list process, it looks like arrays, associative arrays, hash tables, dictionaries or mappings too.

1. Control flow: Structured programming for Ada-like script

Fun uses syntax of Ada. The syntax of Ada is very clear and easy to read and write. The statements are semicolon terminated. Fun differs from Ada, such as "when ... =>" to "when ... do", add "while ... do" and "for ... do", and so on. Exception handling syntax is changed from Delphi. It supports "except" and "finally" at the same time. Remove "on" in "except" due to dynamic typing.

1.1 Conditional statements: if/case

Includes "if..then" and "case..when".

1.1.1 if

  1. ########################################
  2. # if
  3. ########################################
  4. # if expression then cmds
  5. # { elsif expression then cmds } 0..n
  6. # [ else cmds ] 0..1
  7. # end if;
  8. ########################################
  9. if true then
  10.   ?. true; # HIT
  11. end if;
  12. if false then
  13.   ?. false;
  14. else
  15.   ?. true; # HIT
  16. end if;
  17. if false then
  18.   ?. false;
  19. elsif true then
  20.   ?. true; # HIT
  21. else
  22.   ?. "What's wrong with you?";
  23. end if;
  24. ########################################
  25. # 1. Comments start with "#" or "//"
  26. # Comment block: #* ... #
  27. # 2. "true", "false" are keywords
  28. # 3. "?." means output (append extra \r\n)
  29. # "?," means output (append a blank' ')
  30. # "?:" means output (append a TAB )
  31. # "?" means output (without any extra)
  32. ########################################
True True True
Download this DEMO

1.1.2 case

  1. ########################################
  2. # case
  3. ########################################
  4. # case expression is
  5. # { when value do cmds }+ 1..n
  6. # [ else cmds ] 0..1
  7. # end case;
  8. ########################################
  9. var exp = 1;
  10. case exp is
  11.   when 1 do
  12.   ?. 1; # HIT
  13.   when 2 do
  14.   ?. 2;
  15.   when 3 do
  16.   ?. 3;
  17.   else
  18.   ?. 'else';
  19. end case;
  20. exp = "Hello";
  21. case exp is
  22.   when "Good" do
  23.   ?. @ & ' morning!';
  24.   when "Bad" do
  25.   ?. @ & ' command or file name!';
  26.   when "Hello" do
  27.   ?. @ & ', world!'; # HIT
  28.   else
  29.   ?. @ & ' not found!';
  30. end case;
  31. ########################################
  32. # 1. Value in "when" may be anything ([...] or /.../)
  33. # 2. "@" is a built-in variable in "case"
  34. # @ <- expression in "case ... is"
  35. # 3. "&" means string concat
  36. # 4. String quoted with ' or " or `
  37. ########################################
1 Hello, world!
Download this DEMO

1.2 Loop statements: loop

  1. ########################################
  2. # loop
  3. ########################################
  4. # loop
  5. # cmds
  6. # end loop;
  7. ########################################
  8. var i = 1;
  9. loop
  10.   ?. i;
  11.   exit;
  12. end loop;
  13. loop
  14.   exit when i > 9;
  15.   ? i;
  16.   i += 1;
  17. end loop;
  18. ?. '..DONE';
  19. i = 9;
  20. loop
  21.   i -= 1;
  22.   exit when i <= 0;
  23.   next when i mod 2 = 1;
  24.   ? i;
  25. end loop;
  26. ?. '..DONE';
  27. ########################################
  28. # 1. "exit" means exit the loop
  29. # "exit when" means when ... exit ...
  30. # "next" means skip to next loop
  31. # "next when" means when ... next ...
  32. # 2. v += ... means v = v + ...
  33. # v -= ... means v = v - ...
  34. # v *= ... means v = v * ...
  35. # v &= ... means v = v & ...
  36. ########################################
1 123456789..DONE 8642..DONE
Download this DEMO

1.2.1 while

  1. ########################################
  2. # loop-while
  3. ########################################
  4. # while expression loop
  5. # cmds
  6. # end loop;
  7. ########################################
  8. var i = 1;
  9. while i <= 9 loop
  10.   ? i;
  11.   i += 1;
  12. end loop;
  13. ?. '..DONE';
  14. i = 9;
  15. while i > 0 do
  16.   ? i;
  17.   i -= 1;
  18. end do;
  19. ?. '..DONE';
  20. ########################################
  21. # 1. while ... "loop" -> while ... "do"
  22. # end "loop" -> end "do"
  23. ########################################
123456789..DONE 987654321..DONE
Download this DEMO

1.2.2 for

  1. ########################################
  2. # loop-for
  3. ########################################
  4. # for v = e1 to e2 [step e3] loop
  5. # cmds
  6. # end loop;
  7. ########################################
  8. for i = 1 to 9 loop
  9.   ? i;
  10. end loop;
  11. ?. '..DONE';
  12. for i = 9 to 1 step -1 do
  13.   ? i;
  14. end do;
  15. ?. '..DONE';
  16. ########################################
  17. # 1. for ... "loop" -> for ... "do"
  18. # end "loop" -> end "do"
  19. # 2. v is a built-in variable in loop
  20. ########################################
123456789..DONE 987654321..DONE
Download this DEMO

1.2.3 for-in

  1. ########################################
  2. # loop-for-in
  3. ########################################
  4. # for v in expression loop
  5. # cmds
  6. # end loop;
  7. ########################################
  8. # for k : v in expression loop
  9. # cmds
  10. # end loop;
  11. ########################################
  12. for i in [1, 2, 3, 4, 5] loop
  13.   ? i;
  14. end loop;
  15. ?. '..DONE';
  16. for i in [5, 4, 3, 2, 1] do
  17.   ? i;
  18. end do;
  19. ?. '..DONE';
  20. for k: i in [a: 1, b: 2, c: 3] do
  21.   ?, k;
  22.   ?, i;
  23. end do;
  24. ?. 'DONE';
12345..DONE 54321..DONE a 1 b 2 c 3 DONE
Download this DEMO

1.3 Exceptions: try

  1. ########################################
  2. # try
  3. ########################################
  4. # try cmds
  5. # [ except cmds ] 0..1
  6. # [ finally cmds ] 0..1
  7. # end try;
  8. ########################################
  9. try
  10.   ? 'try..'; # HIT
  11. except
  12.   ? 'except..';
  13. end try;
  14. ?. 'DONE';
  15. try
  16.   ? 'try..'; # HIT
  17. finally
  18.   ? 'finally..'; # HIT
  19. end try;
  20. ?. 'DONE';
  21. try
  22.   ? 'try..'; # HIT
  23. except
  24.   ? 'except..';
  25. finally
  26.   ? 'finally..'; # HIT
  27. end try;
  28. ?. 'DONE';
  29. try
  30.   ? 'try..'; # HIT
  31.   ? 1 / 0;
  32.   ? '1 / 0';
  33. except
  34.   ? 'except..'; # HIT
  35.   ? @ & '..'; # HIT
  36. finally
  37.   ? 'finally..'; # HIT
  38. end try;
  39. ?. 'DONE';
  40. try
  41.   ? 'try..'; # HIT
  42.   raise "Stop!";
  43.   ? 'Stop!';
  44. except
  45.   ? 'except..'; # HIT
  46.   ? @ & '..'; # HIT
  47. finally
  48.   ? 'finally..'; # HIT
  49. end try;
  50. ?. 'DONE';
  51. ########################################
  52. # 1. "@" is a built-in variable in "except"
  53. # @ <- exception
  54. # 2. "raise" can throw an exception
  55. # exception can be anything
  56. ########################################
try..DONE try..finally..DONE try..finally..DONE try..except..Floating point division by zero..finally..DONE try..except..Stop!..finally..DONE
Download this DEMO

2. Variables: Dynamic typing in imperative programming

Fun is an imperative language which can change the program state via change the values of variables. Variables are dynamic typing and can convert types automatically when needed. Values can be changed within statements only and can be gotten in any expressions or statements in the scope.

2.1 Name

In FUN, the valid names are /[$_@A-Za-z][$_@A-Za-z0-9]*/ (Regular Expression) limited. In fact, all identifiers (IDs) too. There are 40 reserved keywords cannot be used by programmers: if then elsif else end case is when do loop exit next while for to step in try except finally raise fun return class atom new var use as null nil div mod not and or xor bit true false There are 4 built-in variables in FUN: @ result this base @ is built in "case", "except", "fun" and etc., result is built in "fun", this/base is built in "class".

2.2 Type

Fun's variables have the following types: base types(number, string, bool, time), object types(set, object, class, function) and others. All base types are value types. All object types are reference types, support shallow copy only.
  1. ########################################
  2. # type
  3. ########################################
  4. # Number: [0-9]+(\.[0-9]+)?(e-?[0-9]+)?|0x[0-9a-f]+|0b[01]+
  5. # String: Quoted with ' or " or `
  6. # Time: @String
  7. # Bool: true/false
  8. # Null: null/nil
  9. ########################################
  10. # Number
  11. ?. 123456789;
  12. var n = 1.23456789; ?. n;
  13. n = 0xffffffff; ?. n;
  14. # String
  15. ?. "This is a string.";
  16. var s = 'Hello, string.'; ?. s;
  17. # Time
  18. ?. @"2010-04-09 15:35:15";
  19. var t = @'2010-04-09 15:35:15'; ?. t;
  20. # Bool
  21. ?. true;
  22. var b = false; ?. b;
  23. # Null
  24. ?. '[' & null & ']';
123456789 1.23456789 4294967295 This is a string. Hello, string. 2010-4-9 15:35:15 2010-4-9 15:35:15 True False []
Download this DEMO

2.3 Calculation

Variables can be combined to expressions via calculation. There are some types of expressions and calculations: number, string, bool and etc. The bool expressions can be used as conditions in control flow.
  1. ########################################
  2. # calc
  3. ########################################
  4. # Number: + - * / div mod ^
  5. # Bits: << >> (bit not/and/or/xor)
  6. # String: &
  7. # Time: + -
  8. # Bool: not and or xor
  9. # Regex: =~ !~
  10. # Set: in
  11. # Others: = !=(<>) < <= > >=
  12. # Set/Others for any types
  13. ########################################
  14. # precedence (default left association)
  15. ########################################
  16. # () [] .
  17. # ^
  18. # * / div mod
  19. # (bit not) -> right
  20. # (bit and/or/xor) << >>
  21. # + -
  22. # &
  23. # = != <> < <= > >= in =~ !~ -> none
  24. # not -> right
  25. # and
  26. # or xor
  27. ########################################
  28. # short-circuit calculation
  29. ########################################
  30. # and
  31. # or
  32. ########################################
  33. # Number
  34. var n1 = 9;
  35. var n2 = 3.3;
  36. ?. n1 + n2;
  37. ?. n1 - n2;
  38. ?. n1 * n2;
  39. ?. n1 / n2;
  40. ?. n1 div "4"; # Type conversions automatically
  41. ?. n1 mod '4'; # Type conversions automatically
  42. ?. n1 ^ 3; # power
  43. # Bits
  44. n1 = 0x0f;
  45. n2 = 0xf0;
  46. ?. n1 << 4; # shift left
  47. ?. n2 >> 4; # shift right
  48. ?. bit not n1;
  49. ?. n1 bit and n2;
  50. ?. n1 bit or n2;
  51. ?. n1 bit xor n2;
  52. # String
  53. var s1 = 'Hello';
  54. var s2 = ", world!";
  55. ?. s1 & s2 & ' - ' & 10000; # Type conversions automatically
  56. # Time
  57. var t1 = @"2010-04-09 15:35:15";
  58. var t2 = @'2010-03-09 15:35:15';
  59. ?. t1 + 100;
  60. ?. t1 - t2;
  61. # Bool
  62. var b1 = true;
  63. var b2 = false;
  64. ?. not not b1;
  65. ?. not (b1 and b2);
  66. ?. b1 or b2;
  67. ?. b1 xor b2;
  68. # Set
  69. ?. "Hello" in ["Hello", "World"];
  70. # Others - Compare
  71. ?. not 1 = 2;
  72. ?. 1 != 2;
  73. ?. 1 <> 2;
  74. ?. 1 < 2;
  75. ?. 1 <= 2;
  76. ?. not 1 > 2;
  77. ?. not 1 >= 2;
  78. # Null - All null values equal null (number, string, bool, etc.)
  79. ?. null = 0;
  80. ?. null = false;
  81. ?. null = '';
  82. # Short-circuit calculation
  83. ?. true or 1 = 0; # "1 = 0" doesn't need calc
  84. ?. false and 1 = 1; # "1 = 1" doesn't need calc
12.3 5.7 29.7 2.72727272727273 2 1 729 240 15 4294967280 0 255 255 Hello, world! - 10000 2010-7-18 15:35:15 31 True True True True True True True True True True True True True True True True False
Download this DEMO

2.4 Assignment

Values of variables can be assigned in statements only.
  1. ########################################
  2. # assign
  3. ########################################
  4. # v = expression;
  5. # v += expression;
  6. # v -= expression;
  7. # v *= expression;
  8. # v &= expression;
  9. ########################################
  10. var a = 1; ?. a = 1;
  11. a += 2; ?. a = 3;
  12. a -= 1; ?. a = 2;
  13. a *= 2; ?. a = 4;
  14. a &= 5; ?. a = '45';
True True True True True
Download this DEMO

2.5 Scope

Variables are defined by "var" in a block. A block means a module (file) or any control flow block such as if/elsif/else/case/when/loop or fun/class and etc. Variables accessing always for the nearest block, if not found then for the upper level.
  1. ########################################
  2. # scope
  3. ########################################
  4. var a = 1;
  5. var b = 2;
  6. ?. a = 1;
  7. ?. b = 2;
  8. if true then
  9.   var a = 2; # new "a"
  10.   b = 22; # old "b"
  11.   ?. a = 2;
  12.   ?. b = 22;
  13.   if true then
  14.   var a = 3; # new "a"
  15.   b = 33; # old "b"
  16.   ?. a = 3;
  17.   ?. b = 33;
  18.   end if;
  19.   ?. a = 2;
  20.   ?. b = 33;
  21. end if;
  22. ?. a = 1;
  23. ?. b = 33;
True True True True True True True True True True
Download this DEMO

3. Functions: Procedural and modular programming

Fun supports general procedural programming. Functions in FUN can be defined in any block and the rules of scope are same as scope of variables.

3.1 Functions define and call

  1. ########################################
  2. # fun
  3. ########################################
  4. # fun name ( parameters )
  5. # cmds
  6. # end fun;
  7. ########################################
  8. # Define a function named "foo"
  9. fun foo()
  10.   ?. 'Hello, fun!';
  11. end fun;
  12. # Call function "foo"
  13. foo();
  14. # Define a function with parameters
  15. fun max(a, b)
  16.   if a > b then
  17.   result = a;
  18.   else
  19.   result = b;
  20.   end if;
  21. end fun;
  22. fun min(a, b)
  23.   if a < b then
  24.   return a;
  25.   else
  26.   return b;
  27.   end if;
  28. end fun;
  29. ?. max(1, 9);
  30. ?. max(9, 1);
  31. ?. min(1, 9);
  32. ?. min(9, 1);
  33. ########################################
  34. # 1. "result", "@" are built-in variables in "fun"
  35. # they all be defined as the result value of the fun
  36. # 2. "return" means return the fun
  37. # it can return with/without a value
  38. # 3. "exit" can exit a fun too
  39. ########################################
Hello, fun! 9 9 1 1
Download this DEMO

3.2 Default arguments

  1. ########################################
  2. # fun-default
  3. ########################################
  4. # test define
  5. fun test(a, b, c)
  6.   # embed inner fun
  7.   fun echo(name, str)
  8.   ? name & '=[' & str & '] ';
  9.   end fun;
  10.   # echo the parameters
  11.   echo('a', a);
  12.   echo('b', b);
  13.   echo('c', c);
  14.   ?. 'DONE';
  15. end fun;
  16. test(1, 2, 3);
  17. test(1, 2); # keep param(s) 'c' as null
  18. test(1); # keep param(s) 'b' and 'c' as null
  19. ########################################
  20. # 1. Default arguments always be set as null
  21. ########################################
a=[1] b=[2] c=[3] DONE a=[1] b=[2] c=[] DONE a=[1] b=[] c=[] DONE
Download this DEMO

3.3 Named parameters

  1. ########################################
  2. # fun-named
  3. ########################################
  4. # { name: value } 0..n
  5. ########################################
  6. # test define
  7. fun test(a, b, c)
  8.   # embed inner fun
  9.   fun echo(name, str)
  10.   ? name & '=[' & str & '] ';
  11.   end fun;
  12.   # echo the parameters
  13.   echo('a', a);
  14.   echo('b', b);
  15.   echo('c', c);
  16.   ?. 'DONE';
  17. end fun;
  18. test(a: 1, b: 2, c: 3);
  19. test(c: 1, b: 2, a: 3);
  20. test(c: 1, b: 2); # keep param(s) 'a' as null
  21. test(c: 1); # keep param(s) 'b' and 'a' as null
  22. ########################################
  23. # 1. Default arguments always be set as null
  24. ########################################
a=[1] b=[2] c=[3] DONE a=[3] b=[2] c=[1] DONE a=[] b=[2] c=[1] DONE a=[] b=[] c=[1] DONE
Download this DEMO

3.4 Call by reference

Fun supports call by value (default) and call by reference. You could call by reference when call a function with "var" arguments. All object types (reference types) are passed pointers, not call by reference.
  1. ########################################
  2. # fun-ref
  3. ########################################
  4. fun swap(a, b)
  5.   var t = a;
  6.   a = b;
  7.   b = t;
  8. end fun;
  9. var i = 1;
  10. var j = 9;
  11. ?. i & ' ' & j;
  12. swap(i, j); # Call by value
  13. ?. i & ' ' & j;
  14. swap(var i, var j); # Call by reference
  15. ?. i & ' ' & j;
  16. swap(var i, var j); # Call by reference
  17. ?. i & ' ' & j;
  18. ########################################
  19. # 1. pass "var" arguments to call by reference
  20. ########################################
1 9 1 9 9 1 1 9
Download this DEMO

3.5 Recursions

  1. ########################################
  2. # fun-recursion
  3. ########################################
  4. for i = 1 to 17 do
  5.   ?. fact(i);
  6.   fun fact(n)
  7.   if n > 1 then
  8.   result = n * fact(n - 1); # call fact recursion
  9.   else
  10.   result = 1;
  11.   end if;
  12.   end fun;
  13. end do;
1 2 6 24 120 720 5040 40320 362880 3628800 39916800 479001600 6227020800 87178291200 1307674368000 20922789888000 355687428096000
Download this DEMO

3.6 Uses

Fun supports reuse resources via "use".
  1. ########################################
  2. # use
  3. ########################################
  4. # use string;
  5. ########################################
  6. # use string as id;
  7. ########################################
  8. ?. '----Use fun-ref.fun ...';
  9. use 'fun-ref.fun';
  10. ?. '----Used----';
  11. i = 11;
  12. j = 99;
  13. ?. i & ' ' & j;
  14. swap(i, j); # Call by value
  15. ?. i & ' ' & j;
  16. swap(var i, var j); # Call by reference
  17. ?. i & ' ' & j;
  18. swap(var i, var j); # Call by reference
  19. ?. i & ' ' & j;
  20. use 'fun-ref.fun' as lib; # use as alias
  21. i = 111;
  22. j = 999;
  23. ?. i & ' ' & j;
  24. lib.swap(var i, var j); # use via module_alias.name
  25. ?. i & ' ' & j;
  26. ########################################
  27. # 1. The used file will be inited at first (Run Once)
  28. # 2. Can access the IDs for top level of the used file
  29. # Variables and functions/classes and so on
  30. # 3. The latest IDs are valid for same name
  31. # Multiple files be used
  32. # 4. Can re-name the module as a new id, such as
  33. # use "..." as newone;
  34. # ?. newone.test();
  35. # 5. Files Can be used in anywhere
  36. ########################################
----Use fun-ref.fun ... 1 9 1 9 9 1 1 9 ----Used---- 11 99 11 99 99 11 11 99 111 999 999 111
Download this DEMO

4. Classes: Class-based object-oriented programming

Fun is an object-oriented programming language. It supports class-based single inheritance and polymorphism.

4.1 Classes define and objects create

Fun uses "class" keyword to define classes. Create an instance of class via call the constructor of the class.
  1. ########################################
  2. # class
  3. ########################################
  4. # class name ( parameters )
  5. # cmds
  6. # end class;
  7. ########################################
  8. # define a class
  9. class CA()
  10.   # test for class constructor
  11.   ? 'CA-constructor-starting..';
  12.   # member variable
  13.   var name = 'CA';
  14.   # member function
  15.   fun showName()
  16.   ?. name;
  17.   end fun;
  18.   fun getName()
  19.   return name;
  20.   end fun;
  21.   ?. 'DONE';
  22. end class;
  23. # create a class instance (object)
  24. var a = CA();
  25. # use the member variable of object
  26. ?. a.name;
  27. # use the member function of object
  28. a.showName();
  29. ?. a.getName();
CA-constructor-starting..DONE CA CA CA
Download this DEMO

4.2 Inheritance and polymorphism

In FUN, subclasses are inherited from single base class. When an object was created, constructor of super class was called at first automatically. All same IDs (Variables and functions and etc.) will override from base classes.
  1. ########################################
  2. # class-subclass
  3. ########################################
  4. # class name = base ( parameters )
  5. # cmds
  6. # end class;
  7. ########################################
  8. # define a class
  9. class CA()
  10.   ? 'CA-constructor-starting..';
  11.   var name = 'CA';
  12.   fun showName()
  13.   ?. name;
  14.   end fun;
  15.   fun getName()
  16.   return name;
  17.   end fun;
  18.   ?. 'DONE';
  19. end class;
  20. # define a sub-class
  21. class CB = CA()
  22.   ? 'CB-constructor-starting..';
  23.   name = 'CB';
  24.   ?. 'DONE';
  25. end class;
  26. class CC = CB()
  27.   ? 'CC-constructor-starting..';
  28.   name = 'CC';
  29.   fun showName()
  30.   ?. '--CC.showName() .. ' & name & ' .. DONE';
  31.   end fun;
  32.   ?. 'DONE';
  33. end class;
  34. fun test(o)
  35.   ?. o.name;
  36.   o.showName();
  37.   ?. o.getName();
  38. end fun;
  39. ?. '--CA--';
  40. test( CA() );
  41. ?. '--CB--';
  42. test( CB() );
  43. ?. '--CC--';
  44. test( CC() );
--CA-- CA-constructor-starting..DONE CA CA CA --CB-- CA-constructor-starting..DONE CB-constructor-starting..DONE CB CB CB --CC-- CA-constructor-starting..DONE CB-constructor-starting..DONE CC-constructor-starting..DONE CC --CC.showName() .. CC .. DONE CC
Download this DEMO

4.3 This and base

  1. ########################################
  2. # class-base
  3. ########################################
  4. # class name = base ( parameters )
  5. # cmds
  6. # end class;
  7. ########################################
  8. # this.field or this.method()
  9. # base.field or base.method()
  10. ########################################
  11. // base class
  12. class CBas()
  13.   var field = 'field';
  14.   fun method()
  15.   ?. field;
  16.   end fun;
  17.   fun test()
  18.   ?. field;
  19.   ?. this.field;
  20.   method(); // call the method in this class
  21.   this.method(); // call the override method
  22.   end fun;
  23. end class;
  24. // sub class
  25. class CSub = CBas()
  26.   fun method()
  27.   ? 'CSub.method()..';
  28.   base.method(); // call the method in base classes
  29.   end fun;
  30. end class;
  31. // test ...
  32. var bas = CBas();
  33. var sub = CSub();
  34. ?. '--test--bas--'; ?. bas.field; bas.test();
  35. ?. '--test--sub--'; ?. sub.field; sub.test();
  36. // test ...
  37. bas.field = 'bas';
  38. sub.field = 'sub';
  39. ?. '--test--bas--'; ?. bas.field; bas.test();
  40. ?. '--test--sub--'; ?. sub.field; sub.test();
--test--bas-- field field field field field --test--sub-- field field field field CSub.method()..field --test--bas-- bas bas bas bas bas --test--sub-- sub sub sub sub CSub.method()..sub
Download this DEMO

4.4 Override operators

  1. ########################################
  2. # class-operators-override
  3. ########################################
  4. # this['+'] = fun (right) { ... }
  5. # this['-'] = fun (right) { ... }
  6. # ...
  7. ########################################
  8. class Number(me)
  9.   this['+'] = fun (you) {
  10.   return me + you;
  11.   };
  12.   this['-'] = fun (you) {
  13.   return me - you;
  14.   };
  15.   this['*'] = fun (you) {
  16.   return me * you;
  17.   };
  18.   this['/'] = fun (you) {
  19.   return me / you;
  20.   };
  21.   this['\'] = fun (you) {
  22.   return me div you;
  23.   };
  24.   this['%'] = fun (you) {
  25.   return me mod you;
  26.   };
  27.   this['^'] = fun (you) {
  28.   return me ^ you;
  29.   };
  30.   this['='] = fun (you) {
  31.   return me = you;
  32.   };
  33.   this['!'] = fun (you) {
  34.   return me <> you;
  35.   };
  36.   this['>'] = fun (you) {
  37.   return me > you;
  38.   };
  39.   this['<'] = fun (you) {
  40.   return me < you;
  41.   };
  42. end class;
  43. var n = Number(10);
  44. ?. n .+ 2; // .+ means + override version
  45. ?. n .- 3; // .- means - override version
  46. ?. n .* 4; // .* means * override version
  47. ?. n ./ 5; // ./ means / override version
  48. ?. n .\ 6; // .\ means \ override version
  49. ?. n .% 7; // .% means % override version
  50. ?. n .^ 8; // .^ means ^ override version
  51. ?. n .> 9; // .> means > override version
  52. ?. n .= 10; // .= means = override version
  53. ?. n .< 11; // .< means < override version
  54. ?. n .! 12; // .! means ! override version
  55. ########################################
  56. # 1. Currently FUN supports override operators(16):
  57. # + - * / \ % ^ ! = < > & ~ ? | #
  58. # 2. All override operators same precedence
  59. # 3. All override operators are duality operators
  60. # So the functions will have one parameter
  61. # 4. Must use "." append operators to use them
  62. ########################################
12 7 40 2 1 3 100000000 True True True True
Download this DEMO

4.5 Anything is object

Anything include number, string, set or list, function or class and etc is object.
  1. ########################################
  2. # object
  3. ########################################
  4. # number
  5. ?. (1.atan() * 2).sin();
  6. # string
  7. ?. '123'.length();
  8. ?. 'abc'.upper();
  9. ?. 'ABC'.lower();
  10. # set/list
  11. ?. [a: 1, b: 2, c: 3].a;
  12. var s1 = [
  13.   f1: fun(){
  14.   ?. 'hello, f1';
  15.   },
  16.   f2: fun(){
  17.   ?. 'hello, f2';
  18.   }
  19. ];
  20. s1.f1();
  21. s1.f2();
1 3 ABC abc 1 hello, f1 hello, f2
Download this DEMO

5. Functional programming

Fun is a functional programming language. Fun supports first-class functions and higher-order functions. Fun supports anonymous functions, closures and currying.

5.1 First-class functions and higher-order functions

  1. ########################################
  2. # functional
  3. ########################################
  4. fun foo(a)
  5.   ?. 'Hello, ' & a & '!';
  6. end fun;
  7. var f = foo;
  8. f('functional');
  9. fun high(f, a)
  10.   f(a);
  11. end fun;
  12. var h = high;
  13. h(f, 'functional');
Hello, functional! Hello, functional!
Download this DEMO

5.2 Anonymous functions

  1. ########################################
  2. # functional-anonymous
  3. ########################################
  4. # fun ( parameters ) { cmds }
  5. ########################################
  6. # fun ( ) { cmds }
  7. ########################################
  8. # ( ) { cmds }
  9. ########################################
  10. # { cmds }
  11. ########################################
  12. fun If(a, b, c)
  13.   if a then
  14.   return b();
  15.   elsif c <> null then
  16.   return c();
  17.   end if;
  18. end fun;
  19. fun Loop(a, b)
  20.   while a() do
  21.   b();
  22.   end do;
  23. end fun;
  24. fun For(init, cond, nex1, code)
  25.   init();
  26.   while cond() do
  27.   code();
  28.   nex1();
  29.   end do;
  30. end fun;
  31. fun testIf()
  32.   If(
  33.   true,
  34.   {?.true} # Anonymous function (Lambda calculus)
  35.   );
  36.   If(
  37.   false,
  38.   {?.false}, # Anonymous function (Lambda calculus)
  39.   {?.true} # Anonymous function (Lambda calculus)
  40.   );
  41. end fun;
  42. testIf();
  43. fun testLoop()
  44.   var i = 0;
  45.   var s = 0;
  46.   Loop(
  47.   {return i < 10}, # Anonymous function (Lambda calculus)
  48.   {?, i; i += 1} # Anonymous function (Lambda calculus)
  49.   );
  50.   ?. 'DONE';
  51.   For(
  52.   {i = 1; s = 0}, # Anonymous function (Lambda calculus)
  53.   {@ = i <= 1000}, # Anonymous function (Lambda calculus)
  54.   {i += 1}, # Anonymous function (Lambda calculus)
  55.   {s += i} # Anonymous function (Lambda calculus)
  56.   );
  57.   ?. s;
  58. end fun;
  59. testLoop();
  60. ########################################
  61. # 1. "@" is a built-in variable in "fun"
  62. # @ <- result
  63. # 2. {...} <- (){} <- fun(){}
  64. # with parameters must use
  65. # fun(parameters){} or
  66. # (parameters){}
  67. # 3. "?." means output (append extra \r\n)
  68. # "?," means output (append a blank' ')
  69. # "?:" means output (append a TAB )
  70. # "?" means output (without any extra)
  71. ########################################
True True 0 1 2 3 4 5 6 7 8 9 DONE 500500
Download this DEMO

5.3 Closures

  1. ########################################
  2. # functional-closure
  3. ########################################
  4. fun counter()
  5.   var i = 0;
  6.   return fun(){
  7.   i += 1;
  8.   result = i;
  9.   };
  10. end fun;
  11. var c = counter();
  12. ?. c();
  13. ?. c();
  14. ?. c();
  15. fun mul(bas)
  16.   return fun(times){
  17.   return bas * times;
  18.   };
  19. end fun;
  20. var m = mul(3);
  21. ?. m(4);
  22. ?. m(5);
  23. ?. m(6);
1 2 3 12 15 18
Download this DEMO

5.4 Currying

  1. ########################################
  2. # functional-currying
  3. ########################################
  4. # fun name ( arguments )
  5. ########################################
  6. fun mul(bas, times)
  7.   return bas * times;
  8. end fun;
  9. var m = fun mul(3);
  10. ?. m(4);
  11. ?. m(5);
  12. ?. m(6);
12 15 18
Download this DEMO

5.5 Mathematics functions

  1. ########################################
  2. # functional-mathematics
  3. ########################################
  4. # var name ( arguments ) = exp;
  5. ########################################
  6. # ( arguments ) -> exp
  7. # ( ) -> exp
  8. # argument -> exp
  9. # -> exp
  10. ########################################
  11. var ifv = (condition, vtrue, vfalse){
  12.   if condition then
  13.   return vtrue;
  14.   else
  15.   return vfalse;
  16.   end if;
  17. };
  18. var forto = (start, end1, step1, action){
  19.   result = 0;
  20.   for i = start to end1 step step1 do
  21.   result = action(i, result);
  22.   end do;
  23. };
  24. var sqrt(n) = n ^ 0.5;
  25. var max(a, b) = ifv(a > b, a, b);
  26. var min(a, b) = ifv(a < b, a, b);
  27. var sqrt2 = n -> n ^ 0.5;
  28. var max2 = (a, b) -> ifv(a > b, a, b);
  29. var min2 = (a, b) -> ifv(a < b, a, b);
  30. var sum(s, e, i) = forto(s, e, i, (i, r) -> r + i);
  31. var sum1(n) = sum(1, n, 1);
  32. var fact(n) = forto(1, n, 1, (i, r) -> ifv(r=0, 1, r) * i);
  33. ?. sqrt(9);
  34. ?. max(1, 2);
  35. ?. min(1, 2);
  36. ?. sqrt2(9);
  37. ?. max2(1, 2);
  38. ?. min2(1, 2);
  39. ?. sum(1, 10000, 1);
  40. ?. sum1(10000);
  41. ?. fact(17);
3 2 1 3 2 1 50005000 50005000 355687428096000
Download this DEMO

6. Sets: List process

Fun provides a simple and flexible list. It looks like an array or associative array.

6.1 Arrays

  1. ########################################
  2. # set
  3. ########################################
  4. # [ value, value, value ... ]
  5. ########################################
  6. var list = [0, 1, 2, 3, 4, 5];
  7. ?. 1 in list;
  8. ?. 3 in list;
  9. ?. 5 in list;
  10. ?. not 7 in list;
  11. for i in list do
  12.   ?, i;
  13. end do;
  14. ?. 'DONE';
  15. ?. list[0];
  16. ?. list[1];
  17. ?. list[-1];
  18. ?. list[-2];
  19. list[3] = -3;
  20. list[-1] = -5;
  21. for i in list do
  22.   ?, i;
  23. end do;
  24. ?. 'DONE';
  25. ########################################
  26. # 1. The elements can be anything includes base types and object types
  27. #
  28. # [num: 1, str: "string", time: @'2010-04-23 17:26:22', bool: false]
  29. #
  30. # [[name: 'fun', value: 'function'], [name: 'obj', value: 'object']]
  31. #
  32. # 2. Index of list start from 0 to N-1 and from -N to -1, as below:
  33. #
  34. # var N = list.count();
  35. #
  36. # [ 0 1 2 3 ... N-3 N-2 N-1 ]
  37. # ------------> ++1 --------->
  38. #
  39. # [ 0-N 1-N 2-N 3-N ... -3 -2 -1 ]
  40. # <------------ --1 <---------
  41. #
  42. # !!! Index must be Integer, Don't Use any Float or Double Index !!!
  43. ########################################
True True True True 0 1 2 3 4 5 DONE 0 1 5 4 0 1 2 -3 4 -5 DONE
Download this DEMO

6.2 Mappings: Associative arrays

In FUN, arrays and associative arrays (hash tables, dictionaries, mappings) are same. You could set an element as a name or not.
  1. ########################################
  2. # set-named
  3. ########################################
  4. # [ name: value, name: value ... ]
  5. ########################################
  6. var list = [red: 0x0000ff, green: 0x00ff00, blue: 0xff0000, 0xffff00];
  7. for i in list do
  8.   ?, i;
  9. end do;
  10. ?. 'DONE';
  11. ?, 'red';
  12. ?, list[0];
  13. ?, list['red'];
  14. ?. list.red;
  15. ?, 'green';
  16. ?, list[1];
  17. ?, list['green'];
  18. ?. list.green;
  19. ?, 'blue';
  20. ?, list[2];
  21. ?, list['blue'];
  22. ?. list.blue;
  23. list.yellow = 0x00ffff;
  24. list['white'] = 0xffffff;
  25. list["black"] = 0x000000;
  26. for i in list do
  27.   ?, i;
  28. end do;
  29. ?. 'DONE';
255 65280 16711680 16776960 DONE red 255 255 255 green 65280 65280 65280 blue 16711680 16711680 16711680 255 65280 16711680 16776960 65535 16777215 0 DONE
Download this DEMO

6.3 New set

All set/list defines are constants similar to classes. Only one instance created by compile time. You could get a new set or list instance with "new" keyword or @clone() method.
  1. ########################################
  2. # set-clone
  3. ########################################
  4. # new [...]
  5. ########################################
  6. # s.@clone()
  7. ########################################
  8. var s1 = new [1, 2, 3];
  9. s1.@each((i){?,i}); ?. null;
  10. var s2 = s1.@clone();
  11. s2.@each((i){?,i}); ?. null;
  12. s1[0] = 11;
  13. s2[1] = 22;
  14. s1.@each((i){?,i}); ?. null;
  15. s2.@each((i){?,i}); ?. null;
1 2 3 1 2 3 11 2 3 1 22 3
Download this DEMO

6.4 Library for Set/List

  1. ########################################
  2. # lib-set
  3. ########################################
  4. # built-in (4)
  5. ########################################
  6. # s.@count ()
  7. # s.@each (fun, reverse = false) # fun (val) or (val, key)
  8. # s.@add (v1, v2, ...)
  9. # s.@clone ()
  10. ########################################
  11. fun filter(s, f, n)
  12.   var ret = n or new [];
  13.   s.@each((v){
  14.   if f(v) then
  15.   ret.@add(v);
  16.   end if;
  17.   });
  18.   result = ret;
  19. end fun;
  20. fun find(s, f)
  21.   result = nil;
  22.   for v in s do
  23.   if f(v) then
  24.   return v;
  25.   end if;
  26.   end do;
  27. end fun;
Download this LIB
  1. ########################################
  2. # test for lib-set.fun
  3. ########################################
  4. use '..\lib\lib-set.fun';
  5. test();
  6. fun test()
  7.   ?. [1, 2, 3].@count();
  8.   [1, 2, 3].@each((i){?,i});
  9.   ?. 'DONE';
  10.   var abc = [a: 1, b: 2, c: 3];
  11.   abc.@each((i, k){?,k & '=' & i});
  12.   ?. 'DONE';
  13.   abc.@add(4, 5, 6, g: 7, h: 8, i: 9)
  14.   .@each((i, k){?,k & '=' & i});
  15.   ?. 'DONE';
  16. end fun;
3 1 2 3 DONE a=1 b=2 c=3 DONE a=1 b=2 c=3 =4 =5 =6 g=7 h=8 i=9 DONE
Download this DEMO

6.5 JSON for data-interchange

  1. ########################################
  2. # lib-json
  3. ########################################
  4. # built-in (2)
  5. ########################################
  6. # set.@toJson (format, json) # save set as JSON string
  7. # str.getJson (json = false) # load str as JSON set/list/tree
  8. ########################################
  9. # 1. format param of @toJson()
  10. # default 0, format levels
  11. # join (concat) if format = -1
  12. # 2. json param of @toJson()
  13. # default false, name quoted as "name"
  14. ########################################
Download this LIB
  1. ########################################
  2. # test for lib-json.fun
  3. ########################################
  4. use '..\lib\lib-json.fun';
  5. test();
  6. fun test()
  7.   var s1 = '[1, 2, 3]'.getJson();
  8.   s1.@each((i){?,i});
  9.   ?. '';
  10.   ?. s1.@toJson();
  11.   var s2 = "[{key: str, val: 'this is a string.'},
  12. {key: num, val: 123456789}]".getJson();
  13.   s2.@each(
  14.   (i){
  15.   i.@each(
  16.   (v, k){
  17.   ?, k & ': ' & v;
  18.   }
  19.   );
  20.   ?. null;
  21.   }
  22.   );
  23.   ?. 'format: 0';
  24.   ?. s2.@toJson();
  25.   ?. 'format: 1 level';
  26.   ?. s2.@toJson(format: 1);
  27.   ?. 'format: 2 levels';
  28.   ?. s2.@toJson(format: 2);
  29. end fun;
1 2 3 [1,2,3] key: str val: this is a string. key: num val: 123456789 format: 0 [{key:"str",val:"this is a string."},{key:"num",val:123456789}] format: 1 level [ {key:"str",val:"this is a string."}, {key:"num",val:123456789} ] format: 2 levels [ { key: "str", val: "this is a string." }, { key: "num", val: 123456789 } ]
Download this DEMO

7. Regular expressions

Fun provides a PCRE regular expressions handling engine. The syntax of RE is Perl-Compatible.

7.1 Syntax

A RE (Regular Expression) pattern looks like /[^\/\s]+/[gimsux]*, %[^\%\s]+%[gimsux]* and $("[^"]+"|'[^']+'|`[^`]+`)[gimsux]* (RE). You could also convert a string to RE pattern via using string.toRegex(options). Fun supports built-in functions match() and replace(), such as str.match(re) or re.match(str). Operators of RE: =~ (match) and !~ (not match).

7.2 RE library (match and replace)

  1. ########################################
  2. # lib-regex
  3. ########################################
  4. # built-in (3)
  5. ########################################
  6. # match:
  7. # str.match(str) # match only in string form
  8. #
  9. # str.match(reg) # match in regex pattern
  10. # reg.match(str) # match in regex pattern
  11. # str.match(reg, action) # match in regex pattern
  12. # reg.match(str, action) # match in regex pattern
  13. #
  14. # replace:
  15. # str.replace(str, newstr) # replace all in string form
  16. #
  17. # str.replace(reg, newone) # replace in regex pattern
  18. # reg.replace(str, newone) # replace in regex pattern
  19. #
  20. # toRegex:
  21. # str.toRegex(options) # options: g, i, m, s, u, x
  22. ########################################
  23. # 1. str: string
  24. # reg: regex
  25. # 2. if 'g' in regex option, match() return a list of matched string
  26. # if action exists, the action will be performed with a match
  27. # object argument for every match, and return string concated
  28. # from the return value of the action
  29. # or, match() return a match object with all matched groups
  30. # (matched string is 0 of the groups)
  31. # if action exists, the action will be performed with the match
  32. # object one time, and return string from the return value of
  33. # the action
  34. # 3. if newone is string, replace with the string one time or all
  35. # (according to 'g')
  36. # or if newone is action (function), replace with the return value
  37. # of the action
  38. # 4. options:
  39. # g - global, match or replace all
  40. # i - ignore case, case insensitive
  41. # m - multiple lines, ^ and $ match start or end of any line
  42. # s - single line, dot(.) match any character, even newline(\n)
  43. # u - UTF8
  44. # x - extended, allow regex to contain extra whitespace and comments
  45. # e.g.: '\d+'.toRegex('g')
  46. ########################################
  47. # return left string, the right argument must be var right, e.g.:
  48. # var right = '';
  49. # var left = splitonce(/\./, 'a.b', var right);
  50. # // Now, left = a, right = b
  51. var splitonce(re, str, right) = re.match(str, (m){
  52.   @ = m.missed();
  53.   right = m.rest();
  54.   });
  55. # return a list
  56. var split = (re, str){
  57.   result = new [];
  58.   var m = re.match(str);
  59.   loop
  60.   result.@add(m.missed());
  61.   exit when not m.match();
  62.   end loop;
  63.   result.@add(m.missed());
  64. };
Download this LIB
  1. ########################################
  2. # test for lib-regex.fun
  3. ########################################
  4. use '..\lib\lib-regex.fun';
  5. test();
  6. fun test()
  7.   # str.match(str), return bool
  8.   ?, 'abcd123efg' =~ '123';
  9.   ?, 'abcd123efg' !~ '1234';
  10.   ?, 'abcd123efg' .match( '123' );
  11.   ?. not 'abcd123efg' .match( '1234' );
  12.   # str.match(reg), reg.match(str), return bool
  13.   ?, not not 'abcd123efg' =~ /123/; # Convert to bool
  14.   ?, /1234/ !~ 'abcd123efg';
  15.   ?, not not 'abcd123efg' .match( /123/ );
  16.   ?. not '1234'.toRegex().match( 'abcd123efg' );
  17.   # g, return list of matched string
  18.   'abcd123efg'.match(/\d/g).@each((m){? '[' & m & ']'});
  19.   ?. null;
  20.   # not g, return match object
  21.   ?. 'abcd123efg'.match(/\d+/).value();
  22.   # str.match(reg, action), reg.match(str, action)
  23.   # return string concated from return value of action
  24.   ?. 'abcd123efg'.match(/\d/g, (m){@= '[' & m.value() & ']'});
  25.   ?. 'abcd123efg'.match(/\d/i, (m){@= '[' & m.value() & ']'});
  26.   # str.replace(str, newstr)
  27.   ?. 'abcd123efg'.replace('123', '[123]');
  28.   # str.replace(reg, newstr), reg.replace(str, newstr)
  29.   ?. 'abcd123efg'.replace(/\d/g, '[$0]');
  30.   # str.replace(reg, action), reg.replace(str, action)
  31.   ?. 'abcd123efg'.replace(/\d/g, (m){@= '[' & m.value() * 3 & ']'});
  32.   var right = '';
  33.   var left = splitonce(/\./, 'a.b', var right);
  34.   ?. 'left: [$left], right: [$right]'.eval();
  35.   split('a.b.c.d', /\./).@each((m){?, '[' & m & ']'});
  36.   ?. null;
  37. end fun;
True True True True True True True True [1][2][3] 123 [1][2][3] [1] abcd[123]efg abcd[1][2][3]efg abcd[3][6][9]efg left: [a], right: [b] [a] [b] [c] [d]
Download this DEMO

7.3 Match object

A match object is returned by the match() function without 'g' option and without action. And all action for match() and replace() have a match object parameter.
  1. ########################################
  2. # lib-match (match object)
  3. ########################################
  4. # built-in (6)
  5. ########################################
  6. # m.match() # perform next match, return success or not
  7. #
  8. # m.missed() # return string missed (Left string of matched)
  9. # m.value() # return string matched
  10. # m.value(substi) # return string substitute
  11. # m.@@() # return string matched
  12. # m.@@(substi) # return string substitute
  13. # m.rest() # return string rest (All right string)
  14. #
  15. # m.gcount() # return group count
  16. #
  17. # m.groups(num) # return group by index
  18. # m.groups(str) # return group by name
  19. # m.@(num) # group by index
  20. # m.@(str) # group by name
  21. ########################################
Download this LIB
  1. ########################################
  2. # test for lib-match.fun
  3. ########################################
  4. use '..\lib\lib-match.fun';
  5. test();
  6. fun test()
  7.   var m = 'a.b.c.d' =~ /\./;
  8.   loop
  9.   print(m.missed(), 'missed');
  10.   print(m.value(), 'value');
  11.   print(m.@@(), '@@');
  12.   print(m.rest(), 'rest');
  13.   ?. null;
  14.   exit when not m.match();
  15.   end loop;
  16.   print(m.missed(), 'missed');
  17.   ?. null;
  18.   m = 'a.b.c' =~ /^(?P<first>\w)\.(\w)\.(\w)$/;
  19.   print(m.gcount(), 'Count');
  20.   print(m.groups('first'), 'first');
  21.   ?. null;
  22.   for i = 0 to m.gcount() - 1 do
  23.   print(m.@(i), i);
  24.   end do;
  25.   ?. null;
  26.   fun print(str, name)
  27.   ?, '$name: [$str]'.eval();
  28.   end fun;
  29. end fun;
missed: [a] value: [.] @@: [.] rest: [b.c.d] missed: [b] value: [.] @@: [.] rest: [c.d] missed: [c] value: [.] @@: [.] rest: [d] missed: [d] Count: [4] first: [a] 0: [a.b.c] 1: [a] 2: [b] 3: [c]
Download this DEMO
  1. //Outer brackets: \((\d++(?:\.\d++)?|(?R))(?:[+\-*/](?1))++\)
  2. // Simplify: \((\d+(\.\d+)?|(?R))([+\-*/](?1))+\)
  3. //Inner brackets: ((\d++(?:\.\d++)?|(?3))(?:[+\-*/](?2))++)|(\((?1)\))
  4. // Simplify: ((\d+(\.\d+)?|(?5))([+\-*/](?2))+)|(\((?1)\))
  5. var re = $'
  6. (
  7. (\d++(?:\.\d++)? | (?3))
  8. (?: [+\-*/]
  9. (?2)
  10. )++
  11. )
  12. |
  13. ( \( (?1) \) )
  14. 'x;
  15. ?. re.match('(((1+2-3)*4/5)-((1+2)-((3*4)/((5+(6-7))*(8/9+10.1)/11.2))))').@@();
(((1+2-3)*4/5)-((1+2)-((3*4)/((5+(6-7))*(8/9+10.1)/11.2))))
Download this DEMO

8. Libraries

Fun provides a lightweight basic class library, includes math calculate, string and time process, Windows API and COM, set/list process and regular expression ...

8.1 Math

  1. ########################################
  2. # lib-base
  3. ########################################
  4. fun ifval (condition, vtrue, vfalse)
  5.   if condition then
  6.   return vtrue;
  7.   else
  8.   return vfalse;
  9.   end if;
  10. end fun;
  11. var ifv = ifval;
  12. var ifb(c) = ifv(c, true, false);
  13. fun forloop (start, end1, step1, action, set)
  14.   result = set;
  15.   for i = start to end1 step step1 do
  16.   result = action(i, result);
  17.   end do;
  18. end fun;
  19. var forto = forloop;
  20. var filter = (start, end1, step1, cond, action){
  21.   result = [];
  22.   forto(start, end1, step1, (i, ret){
  23.   if cond(i, ret) then
  24.   action(i, ret);
  25.   end if;
  26.   result = ret;
  27.   }, result);
  28. };
  29. var filter1(s, e, c, a) = filter(s, e, 1, c, a);
  30. fun foreach (set1, action)
  31.   for k: v in set1 do
  32.   action(v, k);
  33.   end do;
  34. end fun;
  35. var forin = foreach;
Download this LIB
  1. ########################################
  2. # lib-math
  3. ########################################
  4. # built-in (6)
  5. ########################################
  6. # a.exp () # e ^ a
  7. # a.log () # LogE(a)
  8. # a.sin ()
  9. # a.cos ()
  10. # a.atan ()
  11. # a.random () # 1.random(), 0.random(), a.random(), -1.random(seed = 0)
  12. ########################################
  13. use 'lib-base.fun';
  14. var pow(a, b) = a ^ b;
  15. var sqrt(a) = a ^ 0.5;
  16. var exp(a) = a.exp();
  17. var log(a) = a.log();
  18. var log2(a) = a.log() / 2.log();
  19. var log10(a) = a.log() / 10.log();
  20. var sin(a) = a.sin();
  21. var cos(a) = a.cos();
  22. var tan(a) = a.sin() / a.cos();
  23. var atan(a) = a.atan();
  24. var asin(a) = atan(a / sqrt(1 - a ^ 2));
  25. var acos(a) = atan(a / sqrt(1 - a ^ 2) * -1) + 2 * atan(1);
  26. var pi() = 1.atan() * 4;
  27. var e() = 1.exp();
  28. var phi() = (5^0.5+1)/2;
  29. var max(a, b) = ifv(a > b, a, b);
  30. var min(a, b) = ifv(a < b, a, b);
  31. var abs(a) = ifv(a < 0, a * -1, a);
  32. //var round(a) = a div 1;
  33. var round(a, b) = a * 10^b div 1 / 10^b;
  34. var random() = 1.random(); # return x in 0..1
  35. var randomize() = 0.random();
  36. var randomint(a) = a.random(); # return x in 0..a
Download this LIB
  1. ########################################
  2. # test for lib-math.fun
  3. ########################################
  4. use '..\lib\lib-math.fun';
  5. test();
  6. fun test()
  7.   ?, 8 = pow(2, 3);
  8.   ?, 2 = sqrt(4);
  9.   ?, e() = exp(1);
  10.   ?, 2 = log(exp(2));
  11.   ?, 3 = log2(pow(2, 3));
  12.   ?. 4 = log10(pow(10, 4));
  13.   ?, 0.000001 > abs(1 - sin(pi() / 6) * 2);
  14.   ?, 0.000001 > abs(1 - cos(pi() / 3) * 2);
  15.   ?, 0.000001 > abs(1 - tan(pi() / 4));
  16.   ?, 0.000001 > abs(pi() - atan(sqrt(3)) * 3);
  17.   ?, 0.000001 > abs(pi() - asin(sqrt(3) / 2) * 3);
  18.   ?. 0.000001 > abs(pi() - acos(sqrt(3) / 2) * 6);
  19.   ?, pi();
  20.   ?. e();
  21.   ?, 9 = max(1, 9);
  22.   ?, 1 = min(1, 9);
  23.   ?, 1 = abs(-1);
  24.   ?, 1 = round(1.4);
  25.   ?, 1 = round(1.4999);
  26.   ?. 2 = round(1.5);
  27.   randomize();
  28.   ?, random() < 1;
  29.   ?, random() < 1;
  30.   ?, random() < 1;
  31.   ?, randomint(100) < 100;
  32.   ?, randomint(100) < 100;
  33.   ?. randomint(100) < 100;
  34. end fun;
True True True True True True True True True True True True 3.14159265358979 2.71828182845905 True True True True True True True True True True True True
Download this DEMO

8.2 String

  1. ########################################
  2. # lib-string
  3. ########################################
  4. # built-in (9)
  5. ########################################
  6. # a.length ()
  7. # a.lower ()
  8. # a.upper ()
  9. # a.subpos (sub)
  10. # a.substr (pos, len) # Default pos=0, len=MAX, can be negative
  11. # a.move (ptr) # ptr: int, copy to ptr
  12. # a.x (n) # Replicate n times, or reverse (n = -1)
  13. # # sort (n = -2)
  14. # a.escape () # \ abtvrnf'"?/\ \x HH \u HHHH
  15. # a.format (A1, A2, ... An) # %s
  16. # a.eval () # $id
  17. ########################################
  18. # 1. a.escape()
  19. # \a \b \t \v \r \n \f
  20. # \' \" \? \/ \\
  21. # \xHH \uHHHH
  22. ########################################
Download this LIB
  1. ########################################
  2. # test for lib-string.fun
  3. ########################################
  4. use '..\lib\lib-string.fun';
  5. test();
  6. fun test()
  7.   var a = 'Www.FunLang.Org';
  8.   ?. a.length();
  9.   ?. a.lower();
  10.   ?. a.upper();
  11.   var b = a.lower();
  12.   ?. b.subpos('fun');
  13.   ?. b.substr();
  14.   ?. b.substr(4);
  15.   ?. b.substr(4, 7);
  16.   ?. b.substr(len: 3);
  17.   ?. b.substr(4, -8);
  18.   ?. b.substr(-3);
  19.   ?. a.substr(4, 7).x(3);
  20.   var c = '[Hello\t\\\r\n\?\x40]';
  21.   ?. c;
  22.   ?. c.escape();
  23.   var d = 'Error: %s at %s/%s.';
  24.   ?. d;
  25.   ?. d.format('"a" not found', 10, 3);
  26.   var name = 'David';
  27.   var e = 'Hello, $name.';
  28.   ?. e;
  29.   ?. e.eval();
  30. end fun;
15 www.funlang.org WWW.FUNLANG.ORG 4 www.funlang.org funlang.org funlang www funlang org FunLangFunLangFunLang [Hello\t\\\r\n\?\x40] [Hello \ ?@] Error: %s at %s/%s. Error: "a" not found at 10/3. Hello, $name. Hello, David.
Download this DEMO

8.3 Date and time

  1. ########################################
  2. # lib-time
  3. ########################################
  4. # built-in (2)
  5. ########################################
  6. # a.time () # 0.time(), a.time()
  7. # a.format() # yyyy-mm-dd hh:nn:ss:zzz
  8. ########################################
  9. var date() = 1.time(); # return date & time
  10. var time() = 0.time(); # return time
  11. var ms = 24 * 60 * 60 * 1000;
  12. class tick()
  13.   var t = time();
  14.   var get = {
  15.   result = (time() - t) * ms div 1;
  16.   t = time();
  17.   };
  18.   var getStr = {
  19.   result = get();
  20.   if result < 100 then
  21.   result = result div 1 & ' milliseconds';
  22.   elsif result < 1000 * 60 then
  23.   result = result div 100 / 10 & ' seconds';
  24.   elsif result < 1000 * 60 * 60 then
  25.   result = result / 1000 div 6 / 10 & ' minutes';
  26.   else
  27.   result = result / 60000 div 6 / 10 & ' hours';
  28.   end if;
  29.   };
  30.   var show = (s, ms){
  31.   if ms = 0 then ms = 1; end if;
  32.   result = s & ': ' & get() / ms;
  33.   };
  34. end class;
Download this LIB
  1. ########################################
  2. # test for lib-time.fun
  3. ########################################
  4. use '..\lib\lib-time.fun';
  5. test();
  6. fun test()
  7.   ?. date();
  8.   ?. time();
  9.   var t = tick();
  10.   var s = 0;
  11.   for i = 1 to 1000000 do
  12.   s += i;
  13.   end do;
  14.   ?, s;
  15.   ?. t.get();
  16. end fun;
2018-9-19 13:27:15 13:27:15 500000500000 156
Download this DEMO

8.4 File

  1. ########################################
  2. # lib-file
  3. ########################################
  4. # built-in (8)
  5. ########################################
  6. # f.load ()
  7. # f.save (str)
  8. # f.find (sub = false) # find directory if f endswith '\'
  9. # f.copy (f2, f3, ...)
  10. # f.move (f2) # delete f if f2 = null
  11. # f.time (flag) # flag: 0-CreationTime, 1-LastWriteTime
  12. # f.size ()
  13. # f.hash (mode) # mode: 0-MD5, 1-SHA1
  14. ########################################
Download this LIB
  1. ########################################
  2. # test for lib-file.fun
  3. ########################################
  4. use '..\lib\lib-file.fun';
  5. test();
  6. fun test()
  7.   var f1 = 'c:\temp\admin\a.tmp';
  8.   var f2 = 'c:\temp\admin\b.tmp';
  9.   var f3 = 'c:\temp\admin\c.tmp';
  10.   var fn = 'c:\temp\admin\?.tmp';
  11.   f1.save('Hello, FUN.');
  12.   ?. f1.load();
  13.   f1.copy(f2, f3);
  14.   ?. f2.load();
  15.   ?. f3.load();
  16.   use '..\lib\lib-base.fun';
  17.   foreach(fn.find(), (f){?.f});
  18.   f1.move();
  19.   f2.move();
  20.   f3.move();
  21.   foreach(fn.find(), (f){?.f});
  22. end fun;
Hello, FUN. Hello, FUN. Hello, FUN. c:\temp\admin\a.tmp c:\temp\admin\b.tmp c:\temp\admin\c.tmp
Download this DEMO

8.5 Windows API

  1. ########################################
  2. # lib-winapi
  3. ########################################
  4. # built-in (2)
  5. ########################################
  6. # f.getapi(name, type)
  7. ########################################
  8. # f.@toCallback(nil, type, ptr)
  9. # f.@toCallback(obj, type, ptr)
  10. ########################################
  11. # 1. f.getapi(name, type)
  12. # f: file name (.dll)
  13. # name: proc name or address
  14. # type: xxx...:x
  15. # n(umber) i(nt) l(ong)
  16. # s(tring) w(idestr) a(nsistr) r(awstr)
  17. # p(ointer) v(oid) c(allback)
  18. # 2. how to call?
  19. # method.call() or method()
  20. #
  21. # e.g.:
  22. #
  23. # # get API
  24. # var msgbox = 'user32'.getapi('MessageBox', 'issi:i');
  25. #
  26. # # call via method.call()
  27. # msgbox.call(0, 'Hello, world!', 'Welcome...', 1);
  28. #
  29. # # or call via method()
  30. # msgbox(0, 'Hello, world!', 'Welcome...', 1);
  31. # 3. f.@toCallback(obj, type, ptr)
  32. # f # fun (function)
  33. # obj # object
  34. # type: xxx...:x # W - BSTR (OleString)
  35. # ptr: true or false # default false
  36. ########################################
Download this LIB
  1. ########################################
  2. # test for lib-winapi.fun
  3. ########################################
  4. use '..\lib\lib-winapi.fun';
  5. test();
  6. fun test()
  7.   # constants
  8.   var WM_SETTEXT = 12;
  9.   var user32 = 'user32';
  10.   # get APIs
  11.   var findwin = user32.getapi('FindWindow', 'ss:i');
  12.   var sendmsg = user32.getapi('SendMessage', 'iiip:i');
  13.   var gettext = user32.getapi('GetWindowText', 'ipi:i');
  14.   # settxt call sendmsg() - WM_SETTEXT
  15.   var settxt(h, t) = sendmsg(h, WM_SETTEXT, 0, t);
  16.   # gettxt call gettext()
  17.   var gettxt = (h){
  18.   result = ' '.x(256);
  19.   var len = gettext(h, var result, 255);
  20.   result = result.substr(len: len);
  21.   };
  22.   # call findwin via findwin.call()
  23.   var handle = findwin.call('Shell_TrayWnd', '');
  24.   # call settxt
  25.   settxt(handle, 'New text.');
  26.   # call gettxt
  27.   ?. '[' & gettxt(handle) & ']';
  28.   # call settxt
  29.   settxt(handle, '');
  30.   # call gettxt
  31.   ?. '[' & gettxt(handle) & ']';
  32. end fun;
[New text.] []
Download this DEMO

8.6 Windows COM

  1. ########################################
  2. # lib-winole
  3. ########################################
  4. # built-in (2)
  5. ########################################
  6. # c.newobj(get = false)
  7. ########################################
  8. # f.@toEvent()
  9. # f.@toEvent(obj)
  10. # f.@toEvent(obj, Source, EventID, DispIDs)
  11. ########################################
  12. # 1. c.newobj(get = false)
  13. # c: class name or id
  14. # get: get an existing COM object
  15. # 2. Call method of ActiveX Object
  16. # obj.Method()
  17. # 3. Property get - @Property
  18. # x = obj.Property # or
  19. # x = obj.@Property() # or
  20. # x = obj.@Property(...) # for Property with params
  21. # 4. Property set - @@Property
  22. # obj.Property = x # or
  23. # obj.@@Property(x) # or
  24. # obj.@@Property(..., x) # for Property with params
  25. # 5. f.@toEvent()
  26. # f # fun (function)
  27. # obj # object
  28. # Source # Windows COM Object
  29. # EventID # IID
  30. # DispIDs # DispID(s)
  31. ########################################
Download this LIB
  1. ########################################
  2. # test for lib-winole.fun
  3. ########################################
  4. use '..\lib\lib-winole.fun';
  5. use '..\lib\lib-base.fun';
  6. test();
  7. fun test()
  8.   var f1 = 'c:\temp\admin\1.tmp';
  9.   var f2 = 'c:\temp\admin\2.tmp';
  10.   var fn = 'c:\temp\admin\?.tmp';
  11.   # Create ActiveX Object
  12.   var sh = 'Wscript.Shell'.newobj();
  13.   f1.save('Windows COM');
  14.   # Call Method of COM Object
  15.   sh.Run('cmd.exe /Ccopy %s %s'.format(f1, f2), 0, true);
  16.   ?. f2.load();
  17.   foreach(fn.find(), (f){?.f; f.move()});
  18.   var regex = 'VBScript.RegExp'.newobj();
  19.   regex.Pattern = '^\d+$'; # Property set, or:
  20.   # regex.@@Pattern('^\d+$');
  21.   ?. regex.Pattern; # Property get, or:
  22.   # ?. regex.@Pattern();
  23.   ?. regex.Test('123'); # Call method
  24.   ?. regex.Test('abc');
  25. end fun;
Windows COM c:\temp\admin\1.tmp c:\temp\admin\2.tmp ^\d+$ True False
Download this DEMO

8.7 Type conversions

  1. ########################################
  2. # lib-type
  3. ########################################
  4. # built-in (5)
  5. ########################################
  6. # a.toStr()
  7. # a.toNum(ptr) #1-int, 2-float, 3-double, -1:ptr
  8. # a.toTime()
  9. # a.toByte(pos) # default 0
  10. # a.toChar()
  11. ########################################
Download this LIB
  1. ########################################
  2. # test for lib-type.fun
  3. ########################################
  4. use '..\lib\lib-type.fun';
  5. test();
  6. fun test()
  7.   ?. 123.toStr() & 456.toStr(); # Auto conversion, same to 123 & 456
  8.   ?. '123'.toNum() * 2; # Auto conversion, same to '123' * 2
  9.   ?. '2010-05-12 15:53:59'.toTime() + 100;
  10.   ?. 'a'.toByte();
  11.   ?. 0x41.toChar();
  12.   if [] then # Auto convert to false
  13.   ?. '[]';
  14.   else
  15.   ?. 'not []'; # HIT
  16.   end if;
  17.   if [1, 2, 3] then # Auto convert to true
  18.   ?. '[1, 2, 3]'; # HIT
  19.   else
  20.   ?. 'not [1, 2, 3]';
  21.   end if;
  22. end fun;
123456 246 2010-8-20 15:53:59 97 A not [] [1, 2, 3]
Download this DEMO

8.8 Dynamic scripting

  1. ########################################
  2. # lib-dyns
  3. ########################################
  4. # built-in (1)
  5. ########################################
  6. # a.compile(inline = false) # file or string
  7. ########################################
  8. # a: file or string
  9. # inline: compile inline to access the current scope
  10. ########################################
Download this LIB
  1. ########################################
  2. # test for lib-dyns.fun
  3. ########################################
  4. use '..\lib\lib-dyns.fun';
  5. test();
  6. fun test()
  7.   // compile a file
  8.   var a = 'lib-file-test.fun'.compile();
  9.   a(); // execute lib-file-test.fun
  10.   a.test(); // call test() in lib-file-test.fun
  11.   // compile a string
  12.   var b = '?. 1 + 2;'.compile();
  13.   b();
  14.   // compile a string inline
  15.   var c = 'b();'.compile(inline: true);
  16.   c(); // call b() in the current scope
  17. end fun;
Hello, FUN. Hello, FUN. Hello, FUN. c:\temp\admin\a.tmp c:\temp\admin\b.tmp c:\temp\admin\c.tmp Hello, FUN. Hello, FUN. Hello, FUN. c:\temp\admin\a.tmp c:\temp\admin\b.tmp c:\temp\admin\c.tmp 3 3
Download this DEMO
  1. var s = `var s = `$s`; ?. s.eval();`; ?. s.eval();
var s = `var s = `$s`; ?. s.eval();`; ?. s.eval();
Download this DEMO

9. Appendix

9.1 Demos

  1. #*======================================
  2.   FFFFFFFF UU UU NN NN
  3.   FF UU UU NNN NN
  4.   FFFFFFF UU UU NN N NN
  5.   FF UU UU NN N NN
  6.   FF UU UU NN NNN
  7.   FF UUUUUU NN NN
  8. ##======================================
  9. var out = output();
  10. class output()
  11.   var head = (s){?. s & '.'.x(20-s.length())};
  12.   var body = (s){?, ' '; ?. s};
  13.   fun close()
  14.   head('end');
  15.   ? '\r\n'.escape();
  16.   end fun;
  17. end class;
  18. var idx;
  19. fun closure(o)
  20.   var i = 0;
  21.   return {
  22.   o.body('index $i'.eval());
  23.   result = i;
  24.   i += 1;
  25.   };
  26. end fun;
  27. fun test(n, f)
  28.   out.head(n);
  29.   idx = closure(out);
  30.   f();
  31.   out.close();
  32. end fun;
  33. test('if', {
  34.   if idx() > idx() and idx() <= idx() then # short-circuit
  35.   out.body('wrong');
  36.   elsif idx() < idx() or idx() >= idx() then # short-circuit
  37.   out.body('right');
  38.   elsif idx() = idx() xor idx() <> idx() then
  39.   out.body('error');
  40.   else
  41.   out.body('error');
  42.   end if;
  43. });
  44. test('case', {
  45.   case idx() is # @ <- idx()
  46.   when idx() do
  47.   out.body('wrong x()');
  48.   when [idx(), idx()] do // or when new ...
  49.   out.body('wrong [x]');
  50.   when '^(%s)$'.format(idx()).toRegex() do
  51.   out.body('wrong /x/');
  52.   when '^($@)$'.eval().toRegex() do
  53.   out.body('right /x/');
  54.   when idx() do
  55.   out.body('error');
  56.   else
  57.   out.body('error');
  58.   end case;
  59. });
  60. test('loop', {
  61.   loop
  62.   exit when idx() < idx();
  63.   end loop;
  64.   for i = idx() to idx() step idx() loop
  65.   out.body((i = 2) & ' - ' & i);
  66.   end loop;
  67.   for k: i in [a: idx(), b: idx(), c: idx()] do // or in new ...
  68.   out.body('$k: $i'.eval());
  69.   end do;
  70.   while idx() < idx() do
  71.   next when idx() mod 2 = 0;
  72.   exit when idx() < idx();
  73.   end do;
  74.   out.body(idx() = 16);
  75. });
  76. test('try', {
  77.   try
  78.   var error() = 1 / 0;
  79.   idx(); error(); idx();
  80.   except # @ <- exception
  81.   out.body('$@ at $@@()'.eval()); # eval $@@ as the last error
  82.   finally
  83.   out.body('final'.x(-1)); # reverse: a.x(-1)
  84.   end try;
  85. });
if.................. index 0 index 1 index 2 index 3 right end................. case................ index 0 index 1 index 2 index 3 index 4 right /x/ end................. loop................ index 0 index 1 index 2 index 3 index 4 True - 2 index 5 index 6 index 7 a: 5 b: 6 c: 7 index 8 index 9 index 10 index 11 index 12 index 13 index 14 index 15 index 16 True end................. try................. index 0 Floating point division by zero at error/89() lanif end.................
Download this DEMO

9.2 Download

Fun.zip

-- THE END of Manual - Funlang.org