import std.traits;

enum isSubroutine(alias F) = is(ReturnType!F == void);

void main() {
    void foo1() {}

    // Calling a function that requires no arguments:
    foo1();
    foo1; // Alternative syntax.

    void foo2(int x, int y) {}

    immutable lambda = function int(int x) => x ^^ 2;

    // Calling a function with a fixed number of arguments:
    foo2(1, 2);
    foo2(1, 2);
    cast(void)lambda(1);

    void foo3(int x, int y=2) {}

    // Calling a function with optional arguments:
    foo3(1);
    foo3(1, 3);

    int sum(int[] arr...) {
        int tot = 0;
        foreach (immutable x; arr)
            tot += x;
        return tot;
    }

    real sum2(Args...)(Args arr) {
        typeof(return) tot = 0;
        foreach (immutable x; arr)
            tot += x;
        return tot;
    }

    // Calling a function with a variable number of arguments:
    assert(sum(1, 2, 3) == 6);
    assert(sum(1, 2, 3, 4) == 10);
    assert(sum2(1, 2.5, 3.5) == 7);

    // Calling a function with named arguments:
    // Various struct or tuple-based tricks can be used for this,
    // but currently D doesn't have named arguments.

    // Using a function in statement context (?):
    if (1)
        foo1;

    // Using a function in first-class context within an expression:
    assert(sum(1) == 1);

    auto foo4() { return 1; }

    // Obtaining the return value of a function:
    immutable x = foo4;

    // Distinguishing built-in functions and user-defined functions:
    // There are no built-in functions, beside the operators, and
    // pseudo-functions like assert().

    int myFynction(int x) { return x; }
    void mySubroutine(int x) {}

    // Distinguishing subroutines and functions:
    // (A subroutine is merely a function that has no explicit
    // return statement and will return void).
    pragma(msg, isSubroutine!mySubroutine); // Prints: true
    pragma(msg, isSubroutine!myFynction);   // Prints: false

    void foo5(int a, in int b, ref int c, out int d, lazy int e, scope int f) {}

    // Stating whether arguments are passed by value, by reference, etc:
    alias STC = ParameterStorageClass;
    alias psct = ParameterStorageClassTuple!foo5;
    static assert(psct.length == 6); // Six parameters.
    static assert(psct[0] == STC.none);
    static assert(psct[1] == STC.none);
    static assert(psct[2] == STC.ref_);
    static assert(psct[3] == STC.out_);
    static assert(psct[4] == STC.lazy_);
    static assert(psct[5] == STC.scope_);
    // There are also inout and auto ref.

    int foo6(int a, int b) { return a + b; }

    // Is partial application possible and how:
    import std.functional;
    alias foo6b = partial!(foo6, 5);
    assert(foo6b(6) == 11);
}


void main() {
  // Function definition
  // See the "Function definition" task for more info
  void noArgs() {}
  void fixedArgs(int arg1, int arg2) {}
  void optionalArgs([int arg1 = 1]) {}
  void namedArgs({required int arg1}) {}
  int returnsValue() {return 1;}

  // Calling a function that requires no arguments
  noArgs();

  // Calling a function with a fixed number of arguments
  fixedArgs(1, 2);

  // Calling a function with optional arguments
  optionalArgs();
  optionalArgs(2);

  // Calling a function with named arguments
  namedArgs(arg1: 1);

  // Using a function in statement context
  if (true) {
    noArgs();
  }

  // Obtaining the return value of a function
  var value = returnsValue();
}


# all functions used are from the standard library
# calling a function with no arguments:
random-int
# calling a function with a fixed number of arguments:
+ 1 2
# calling a function with optional arguments:
# optional arguments are not really possible as such
# generally differently named functions are used:
sort [ 3 2 1 ]
sort-by @len [ "Hello" "World" "Bob" ]
# calling a function with a variable number of arguments:
# generally with a special terminator value, which one depends
# on the function called
concat( 1 2 3 )
[ 1 2 3 ]
set{ :foo :bar :spam }
# calling a function with named arguments: not possible
# using a function in first-class context within an expression
$ @-- @len # $ is "compose", so the function returned is "one less than the length"
# obtaining the return value of a function
# return values are always pushed on the stack, so you don't need anything special
random-int
# discarding the return value of a function
drop random-int
# method call:
local :do { :nuthin @pass }
do!nuthin
!import!fooModule # same as eva!import :fooModule
# arguments are passed by object-identity, like in Python and Lua
# partial application is not possible, due to the fact that
# a function's arity is a property of its behavior and not
# of its definition


var c0 := { console.writeLine("No argument provided") };
var c2 := (int a, int b){ console.printLine("Arguments ",a," and ",b," provided") };


# Anonymous function

foo = fn() ->
  IO.puts("foo")
end

foo()  #=> undefined function foo/0
foo.() #=> "foo"

# Using `def`

defmodule Foo do
  def foo do
    IO.puts("foo")
  end
end

Foo.foo    #=> "foo"
Foo.foo()  #=> "foo"

# Calling a function with a fixed number of arguments

defmodule Foo do
  def foo(x) do
    IO.puts(x)
  end
end

Foo.foo("foo") #=> "foo"

# Calling a function with a default argument

defmodule Foo do
  def foo(x \\ "foo") do
    IO.puts(x)
  end
end

Foo.foo()      #=> "foo"
Foo.foo("bar") #=> "bar"

# There is no such thing as a function with a variable number of arguments. So in Elixir, you'd call the function with a list

defmodule Foo do
  def foo(args) when is_list(args) do
    Enum.each(args, &(IO.puts(&1)))
  end
end

# Calling a function with named arguments

defmodule Foo do
  def foo([x: x]) do
    IO.inspect(x)
  end
end


no_argument()
one_argument( Arg )
optional_arguments( Arg, [{opt1, Opt1}, {another_opt, Another}] )
variable_arguments( [Arg1, Arg2 | Rest] )
names_arguments([{name1, Arg1}, {another_name, Another}] )
% Statement context?
% First class context?
Result = obtain_result( Arg1 )
% No way to distinguish builtin/user functions
% Subroutines?
% Arguments are passed by reference, but you can not change them.
% Partial application is possible (a function returns a function that has one argument bound)


// No arguments
noArgs()

// Fixed number of arguments
oneArg x

// Optional arguments
// In a normal function:
optionalArgs <| Some(5) <| None
// In a function taking a tuple:
optionalArgsInTuple(Some(5), None)
// In a function in a type:
foo.optionalArgs 5;;
// However, if you want to pass more than one paramter, the arguments must be
// passed in a tuple:
foo.optionalArgs(5, 6)

// Function with a variable number of arguments
variableArgs 5 6 7 // etc...

// Named arguments can only be used in type methods taking a tuple. The
// arguments can appear in any order.
foo.namedArgs(x = 5, y = 6)

// Using a function in a statement
for i = 0 to someFunc() do
    printfn "Something"

// Using a function in a first-class context
funcArgs someFunc

// Obtaining a return value
let x = someFunc()

// Built-in functions: do functions like (+) or (-) count?

// Parameters are normally passed by value (as shown in the previous examples),
// but they can be passed by reference.
// Passing by reference:
refArgs &mutableVal

// Partial application example
let add2 = (+) 2


a-function         \ requiring no arguments
a-function         \ with a fixed number of arguents
a-function         \ having optional arguments
a-function         \ having a variable number of arguments
a-function         \ having such named arguments as we have in Forth
' a-function var ! \ using a function in a first-class context (here: storing it in a variable)
a-function         \ in which we obtain a function's return value

                   \ forth lacks 'statement contenxt'
                   \ forth doesn't distinguish between built-in and user-defined functions
                   \ forth doesn't distinguish between functions and subroutines
                   \ forth doesn't care about by-value or by-reference

\ partial application is achieved by creating functions and manipulating stacks
: curried  0 a-function ;
: only-want-third-argument 1 2 rot a-function ;

\ Realistic example:
: move ( delta-x delta-y -- )
  y +!  x +! ;

: down ( n -- )  0 swap move ;
: up ( n -- )    negate down ;
: right ( n -- ) 0 move ;
: left ( n -- )  negate right ;


program main
implicit none
integer :: a
integer :: f, g
logical :: lresult
interface
  integer function h(a,b,c)
    integer :: a, b
    integer, optional :: c
  end function
end interface
write(*,*) 'no arguments: ', f()
write(*,*) '-----------------'
write(*,*) 'fixed arguments: ', g(5,8,lresult)
write(*,*) '-----------------'
write(*,*) 'optional arguments: ', h(5,8), h(5,8,4)
write(*,*) '-----------------'
write(*,*) 'function with variable arguments: Does not apply!'
write(*,*) 'An option is to pass arrays of variable lengths.'
write(*,*) '-----------------'
write(*,*) 'named arguments: ', h(c=4,b=8,a=5)
write(*,*) '-----------------'
write(*,*) 'function in statement context: Does not apply!'
write(*,*) '-----------------'
write(*,*) 'Fortran passes memory location of variables as arguments.'
write(*,*) 'So an argument can hold the return value.'
write(*,*) 'function result: ', g(5,8,lresult) , ' function successful? ', lresult
write(*,*) '-----------------'
write(*,*) 'Distinguish between built-in and user-defined functions: Does not apply!'
write(*,*) '-----------------'
write(*,*) 'Calling a subroutine: '
a = 30
call sub(a)
write(*,*) 'Function call: ', f()
write(*,*) '-----------------'
write(*,*) 'All variables are passed as pointers.'
write(*,*) 'Problems can arise if instead of sub(a), one uses sub(10).'
write(*,*) '-----------------'
end program

!no argument
integer function f()
f = 10
end function

!fixed number of arguments
integer function g(a, b, lresult)
integer :: a, b
logical :: lresult
g = a+b
lresult = .TRUE.
end function

!optional arguments
integer function h(a, b, c)
integer :: a, b
integer, optional :: c

h = a+b
if(present(c)) then
  h = h+10*c
end if
end function

!subroutine
subroutine sub(a)
integer :: a
a = a*100
write(*,*) 'Output of subroutine: ', a
end subroutine


component call_a_function
  export Executable
  (* Declaring test functions that allow the various ways to call functions in Fortress to be demonstrated. *)
  addition(i:ZZ32, j:ZZ32): ZZ32 = i+j
  addition(i:ZZ32): ZZ32 = i+1

  (* Strings are concatenated by using a space as an infix operator. *)
  addition(i:String, j:String): String = i j

  printAString(s:String): () = println(s)

  (* Functions can be passed to other functions as arguments. When passing a function as an argument, the argument's type should be
  represented as follows: "typeOfArgument(s)->returnType," which, in this case, is "String->()." You could also technically use the
  "Any" type, but that isn't type-safe. *)
  printAString(s:String, f:String->()) = f(s)

  (* Defined functions can then be called as follows. *)
  var x:ZZ32 = addition(1, 2)
  var str:String = addition("This is ", "another string.")

  run() = do
    (* You can call built-in functions the same way that you call functions that you define. *)
    println("x at start: " x)

    x := addition(x, 2)

    println("x at middle: " x)

    printAString("This " "is " "a " "string.")
    printAString(str)
    printAString("\nThis is a string that is being printed by a function of the same name \nthat takes a function as an argument.\n",
      printAString)

    x := addition(4)

    println("x at end: " x)
  end
end


Sub Saludo()
    Print "Hola mundo!"
End Sub

Function Copialo(txt As String, siNo As Short, final As String = "") As String
    Dim nuevaCadena As String

    For cont As Short = 1 To siNo
        nuevaCadena &= txt
    Next

    Return Trim(nuevaCadena) & final
End Function

Sub testNumeros(a As Integer, b As Integer, c As Integer = 0)
	Print a, b, c
End Sub

Sub testCadenas(txt As String)
    For cont As Byte = 0 To Len(txt)
        Print Chr(txt[cont]); "";
    Next cont
End Sub

Saludo
Print Copialo("Saludos ", 6)
Print Copialo("Saludos ", 3, "!!")
?
testNumeros(1, 2, 3)
testNumeros(1, 2)
?
testCadenas("1, 2, 3, 4, cadena, 6, 7, 8, \'incluye texto\'")


Public Sub Main()

Hello
Print CopyIt("Hello ", 6)
Print CopyIt("Hello ", 3, "!!")

End
'_____________________________________________________________________________________
Public Sub CopyIt(sString As String, siNo As Short, Optional sEnd As String) As String
Dim siCount As Short
Dim sNewString As String

For siCount = 1 To siNo
  sNewString &= sString
Next

Return Trim(sNewString) & sEnd

End
'_____________________________________________________________________________________
Public Sub Hello()

Print "Hello world!"

End


-- Calling a function with a fixed number of arguments
multiply x y = x * y
multiply 10 20 -- returns 200

-- Calling a function that requires no arguments
-- Normally, you use constant instead of function without arguments:
twopi = 6.28
-- But you can also pass special value as the first argument indicating function call:
twopi () = 6.28 -- definition
twopi :: Num a => () -> a -- its type
twopi () -- returns 6.28

-- Partial application and auto-currying is built-in.
multiply_by_10 = (10 * )
map multiply_by_10 [1, 2, 3] -- [10, 20, 30]
multiply_all_by_10 = map multiply_by_10
multiply_all_by_10 [1, 2, 3] -- [10, 20, 30]

-- TODO:
-- Calling a function with optional arguments
-- Calling a function with a variable number of arguments
-- Calling a function with named arguments
-- Using a function in statement context
-- Using a function in first-class context within an expression
-- Obtaining the return value of a function
-- Distinguishing built-in functions and user-defined functions
-- Distinguishing subroutines and functions
-- Stating whether arguments are passed by value or by reference


//The type of the function argument determines whether or not the value is passed by reference or not.
//Eg. numbers are passed by value and lists/arrays are passed by reference.

software {
	print() 					//Calling a function with no arguments.
	print("Input a number!")	//Calling a function with fixed arguments.
	print(1,2,3,4,5,6,7,8,9,0) 	//Calling a function with variable arguments.
	input = read() 				//Obtaining the return value of a function.
	myprint = print
	myprint("It was: ", input)	//Calling first class functions, the same as calling ordinary functions.

	//The only distinction that can be made between two functions is if they are 'real' or not.
	if type(myprint) = concept
		print("myprint is a not a real function")
	else if type(myprint) = function
		print("myprint is a real function")
	end

	//Partial functions can be created with static parts.
	DebugPrint = print["[DEBUG] ", text]
	DebugPrint("partial function!")		//This would output '[DEBUG] partial function!'

	if type(DebugPrint) = concept
		print("DebugPrint is a not a real function")
	else if type(DebugPrint) = function
		print("DebugPrint is a real function")
	end
}


procedure main()  # demonstrate and describe function calling syntax and semantics

   # normal procedure/function calling

   f()                      # no arguments, also command context
   f(x)                     # fixed number of arguments
   f(x,h,w)                 # variable number of arguments (varargs)
   y := f(x)                # Obtaining the returned value of a function

   # procedures as first class values and string invocation

   f!L                      # Alternate calling syntax using a list as args
   (if \x then f else g)()  # call (f or g)()
   f := write               # assign a procedure
   f("Write is now called") # ... and call it
   "f"()                    # string invocation, procedure
   "-"(1)                   # string invocation, operator

   # Co-expressions

   f{e1,e2}                 # parallel evaluation co-expression call
                            # equivalent to f([create e1, create e2])
   expr @ coexp             # transmission of a single value to a coexpression
   [e1,e2]@coexp            # ... of multiple values (list) to a coexpression
   coexp(e1,e2)             # ... same as above but only in Unicon

   # Other

   f("x:=",1,"y:=",2)       # named parameters (user defined)
end


var foo = function() { return arguments.length };
foo() // 0
foo(1, 2, 3) // 3


#  Calling a function that requires no arguments:
f() = print("Hello world!")
f()

#  Calling a function with a fixed number of arguments:
function f(x, y, z)
    x*y - z^2
end

f(3, 4, 2)

#  Calling a function with optional arguments:
#  Note Julia uses multiple dispatch based on argument number and type, so
# f() is always different from f(x) unless default arguments are used, as in:

pimultiple(mult=1.0) = pi * mult # so pimultiple() defaults to pi * (1.0) or pi

#  Calling a function with a variable number of arguments:

f(a,b,x...) = reduce(+, 0, x) - a - b

# here a and b are single arguments, but x is a tuple of x plus whatever follows x, so:
a = b = c = d = e = 3
f(a,b,c)           # x within the function is (c) so == 0 + c - a - b
f(a,b,c,d,e)      # x is a tuple == (c,d,e) so == (0 + c + d + e) - a - b
f(a,b)             # x is () so == 0 - a - b

#  Calling a function with named arguments:
# Functions with keyword arguments are defined using a semicolon in the function signature,
#  as in
#             function plot(x, y; style="solid", width=1, color="black")
#
# When the function is called, the semicolon is optional, so plot here can be
# either called with plot(x, y, width=2) or less commonly as plot(x, y; width=2).

#  Using a function in statement context:
#  Any function can be used as a variable by its name.

circlearea(x) = x^2 * pi
map(circlearea, [r1, r2, r3, r4])

#  Using a function in first-class context within an expression:
cylindervolume = circlearea(r) * h

#  Obtaining the return value of a function:
radius = 2.5
area = circlearea(2.5)

#  Distinguishing built-in functions and user-defined functions:
#  Julia does not attempt to distinguish these in any special way,
#  but at the REPL command line there is ? help available for builtin
#  functions that would not generally be available for the user-defined ones.

#  Distinguishing subroutines and functions:
#  All subroutines are called functions in Julia, regardless of whether they return values.

#  Stating whether arguments are passed by value or by reference:
#  As in Python, all arguments are passed by pointer reference, but assignment to a passed argument
#  only changes the variable within the function. Assignment to the values referenced by the argument
## DOES however change those values. For instance:

a = 3
b = [3]
c = [3]

function f(x, y)
    a = 0
    b[1] = 0
    c = [0]
end # a and c are now unchanged but b = [0]

#  Is partial application possible and how:
#  In Julia, there are many different ways to compose functions. In particular,
#  Julia has an "arrow" operator -> that may be used to curry other functions.

f(a, b) = a^2 + a + b
v = [4, 6, 8]
map(x -> f(x, 10), v)  # v = [30, 52, 82]


// version 1.0.6

fun fun1() = println("No arguments")

fun fun2(i: Int) = println("One argument = $i")

fun fun3(i: Int, j: Int = 0) = println("One required argument = $i, one optional argument = $j")

fun fun4(vararg v: Int) = println("Variable number of arguments = ${v.asList()}")

fun fun5(i: Int) = i * i

fun fun6(i: Int, f: (Int) -> Int) = f(i)

fun fun7(i: Int): Double = i / 2.0

fun fun8(x: String) = { y: String -> x + " " + y }

fun main(args: Array<String>) {
    fun1()              // no arguments
    fun2(2)             // fixed number of arguments, one here
    fun3(3)             // optional argument, default value used here
    fun4(4, 5, 6)       // variable number of arguments
    fun3(j = 8, i = 7)  // using named arguments, order unimportant
    val b = false
    if (b) fun1() else fun2(9)        // statement context
    println(1 + fun6(4, ::fun5) + 3)  // first class context within an expression
    println(fun5(5))    // obtaining return value
    println(Math.round(2.5)) // no distinction between built-in and user-defined functions, though former usually have a receiver
    fun1()              // calling sub-routine which has a Unit return type by default
    println(fun7(11))   // calling function with a return type of Double (here explicit but can be implicit)
    println(fun8("Hello")("world"))   // partial application isn't supported though you can do this
}


The command

replace   :a0 :a1 ... an-1
     in   expression containing some occurences of :ai
     by   v0 v1 ... vp-1

is rewritten in a prefixed parenthesized form

{{lambda {:a0 :a1 ... an-1}
          expression containing some occurences of :ai}
          v0 v1 ... vp-1}

so called IIFE (Immediately Invoked Function Expression), and defines an anonymous function containing a sequence of n arguments :ai, immediately invoked on a sequence of p values vi, and returning the expression in its body as so modified:

1) if p < n     (partial application)

• the occurrences of the p first arguments are replaced in the function's body by the corresponding p given values,
• a function waiting for missing n-p values is created,
• and its reference is returned.
• example:
{{lambda {:x :y} ... :y ... :x ...} hello}
-> {lambda {:y} ... :y ... hello ...}    // replaces :x by hello
-> LAMB_123                              // the new functions's reference
• called with the value world this function will return ... world ... hello ...

2) if p = n     (normal application)

• the occurences of the n arguments are replaced in the function's body by the corresponding p given values,
• the body is evaluated and the result is returned.
• example
{{lambda {:x :y} ... :y ... :x ...} hello world}
-> {{lambda {:y} ... :y ... hello ...} world}  // replaces :x by hello
-> {{lambda {} ... world ... hello ...} }      // replaces :y by world
->             ... world ... hello ...         // the value

3) if p > n    (variadicity)

• the occurrences of the n-1 first arguments are replaced in the function's body by the corresponding n-1 given values,
• the occurrences of the last argument are replaced in the body by the sequence of p-n supernumerary values,
• the body is evaluated and the result is returned.
• example:
{{lambda {:x :y} ... :y ... :x ...} hello world good morning}
-> {{lambda {:y} ... :y ... hello ...} world good morning}
-> {{lambda {} ... world good morning ... hello ...}}
->             ... world good morning ... hello ...        // the value

More can be seen in http://lambdaway.free.fr/lambdawalks/?view=lambda


foo (1, 2, 3). ; (1) Ordinary call
foo ().        ; (2) No arguments
foo.           ; (3) Equivalent to (2)
foo (1).       ; (4) Single-argument function
foo 1.         ; (5) Equivalent to (4)
foo (bar).     ; (6) Parentheses necessary here since bar is not a literal
foo: 1, 2, 3.  ; (7) Alternative syntax, equivalent to (1)


(defun my-func()
  (: io format '"I get called with NOTHING!~n"))


'Call a function - Liberty BASIC

'First, function result could not be discarded
' that is, you cannot do "f(x)" as a separate statement

'Calling a function that requires no arguments
res = f()   'brackets required

'Calling a function with a fixed number of arguments
res = g(x)
res = h(x,y)
'Calling a function with optional arguments
    'impossible for user-defined functions
    'Some build-in functions ex. INSTR and MID$ could be called with last argument omitted
'Calling a function with a variable number of arguments
    'impossible
'Calling a function with named arguments
    'impossible
'Using a function in statement context
    'impossible (see starting notice)
'Using a function in first-class context within an expression
    'impossible
'Obtaining the return value of a function
res = g(x)
'Distinguishing built-in functions and user-defined functions
    'I would say impossible. Though built-in functions could be EVAL'ed,
    'while user-defined would not be called (tries address array instead).
    'Still cannot distinguish user-defined function from array.
'Distinguishing subroutines and functions
    'then defined, subroutines and functions defined with words
    'SUB and FUNCTION (case incensitive)
    'Then used, function used as expression (with return value),
    res = g(x)
    'while subroutines called with special keyword CALL and without brackets
    call test x, y
'Stating whether arguments are passed by value or by reference
    'Variables passed as arguments into functions and subs are passed "by value" by default
    'parameters could be passed "by reference" if formal parameter in sub/function definition uses the "byref" specifier
    'Then calling a function, you can prevent pass by reference by changing variable to expression
    '   like x+0, x$+"" or just (x), (x$)
'Is partial application possible and how
    'impossible


foo()
-- or alternatively:
call(#foo, _movie)


// Calling a function that requires no arguments
void foo() {puts("Calling a function with no arguments");}
foo();

// Calling a function with a fixed number of arguments
abs(-36);

// Calling a function with optional arguments
puts(nonewline: "nonewline is an optional argument");
puts("\n");

// Calling a function with a variable number of arguments
void var_arg_func(...args) {
    puts(length(args));
}
var_arg_func(1, 2);
var_arg_func(1, 2, 3);

// Obtaining the return value of a function
int s = clock("seconds"); //current time in seconds
// Calling a function with named arguments
// format is a named argument in Clock_format
int str = Clock_format(s, format: "%B");
puts(str);

// Stating whether arguments are passed by value or by reference
void f(int a, int &b) { a++; b++; }
{
int a = 0;
int b = 0;

f(a, &b);
puts (a);
puts (b);
}


-- Lua functions accept any number of arguments; missing arguments are nil-padded, extras are dropped.
function fixed (a, b, c) print(a, b, c) end
fixed() --> nil nil nil
fixed(1, 2, 3, 4, 5) --> 1 2 3

-- True vararg functions include a trailing ... parameter, which captures all additional arguments as a group of values.
function vararg (...) print(...) end
vararg(1, 2, 3, 4, 5) -- 1 2 3 4 5

-- Lua also allows dropping the parentheses if table or string literals are used as the sole argument
print "some string"
print { foo = "bar" } -- also serves as a form of named arguments

-- First-class functions in expression context
print(("this is backwards uppercase"):gsub("%w+", function (s) return s:upper():reverse() end))

-- Functions can return multiple values (including none), which can be counted via select()
local iter, obj, start = ipairs { 1, 2, 3 }
print(select("#", (function () end)())) --> 0
print(select("#", unpack { 1, 2, 3, 4 })) --> 4

-- Partial application
function prefix (pre)
    return function (suf) return pre .. suf end
end

local prefixed = prefix "foo"
print(prefixed "bar", prefixed "baz", prefixed "quux")

-- nil, booleans, and numbers are always passed by value. Everything else is always passed by reference.
-- There is no separate notion of subroutines
-- Built-in functions are not easily distinguishable from user-defined functions


/* Calling a function that requires no arguments */
f();;

/* Calling a function with a fixed number of arguments */
f(1,2);;

/* Calling a function with optional arguments
   Note: defining the function is cumbersome but will get easier in future versions. */
f(1,2,new {default with x=3, y=4});;

/* Calling a function with a variable number of arguments */
printf("%d %d %d %d":char*,2,3,4,5);;

/* Calling a function with named arguments
   Note: may get syntax sugar in future versions */
f(1,2,new {default with x=3, y=4});;

/* Using a function in statement context (what?) */
f();f();f();;

/* Using a function in first-class context within an expression */
[1,2,3].map(string);;

/* Obtaining the return value of a function */
let x:int = f();;

/* Distinguishing built-in functions and user-defined functions */
/* Builtin function i.e. custom calling convention: */
(@ binop "==" l r);;
/* User defined function i.e. normal function */
f(l)(r);;

/* Distinguishing subroutines and functions: both are supported, but compiler is not aware of difference */
sub();;
fun();;

/* Stating whether arguments are passed by value or by reference */
f(value);; /* by value */
f(&value);; /* by pointer reference */
f(ref(value));; /* by managed reference */

/* Is partial application possible and how */
tasty_curry(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)(m)(n)(o)(p)(q)(r)(s)(t)(u)(v)(w)(x)(y)(z);;


// Calling a function that requires no arguments
  ModuleA    ' introduce a namespace can have modules/functions/subs, anything inside, and threads.
  Call FunctionA() ' introduce a namespace can have modules/functions/subs, anything inside.
  Call LambdaA() ' introduce a namespace can have modules/functions/subs, anything inside.
  SubAlfa()  ' subroutine this has the same scope as the caller, we can use Local statement to shadow variables/arrays
  Print @Simple()  ' simple function this has the same scope as the caller, we can use Local statement to shadow variables/arrays
  Gosub labelA  ' Statement Return used to return from a gosub, no arguments and no local statement used, the code is like any other code in the module/function/lambda scope. No jump out of scope allowed.
  Gosub 10020   ' Statement Return used to return from a gosub,, no arguments and no local statement used, the code is like any other code in the module/function/lambda scope. No jump out of scope allowed.
// Calling a function with a fixed number of arguments
  ModuleA 100
  SubAlfa(100)  ' subroutine
  Print @Simple(100)  ' simple function
  Call FunctionA(100)
  Call LambdaA(100)
//  Calling a function with optional arguments
  ModuleA ?,4
  SubAlfa(?)  ' subroutine
  Print @Simple(?)  ' simple function
  Call FunctionA(,4)
  Call LambdaA(,4)
//  Calling a function with a variable number of arguments
  Call FunctionA(1,2,3,4,5)
  Call LambdaA(1,2,3,4,5)
//  Calling a function with named arguments
  ModuleA %X=10, %Z=20
//  Using a function in statement context
  Module A
  SubAlfa()
  Call Void FunctionA()
  Call Void LambdaA()
//  Using a function in first-class context within an expression
  Print (lambda (x,y)->{=x**y}(2,3))*8=64
//  Obtaining the return value of a function
  A%=FunctionA%()  ' integer part from any numeric type. Also A% if get decimals convert to integer using school rounding (0.5, so 3.5 is 4, 2.5 is 3)
  A=FunctionA()   ' numeric or object
  A$=FunctionA$() ' string or object which return string
  A=LambdaA()
  A$=LambdaA$()
  [email protected]()
  [email protected]$()
//  Distinguishing built-in functions and user-defined functions
  Def Cos(x)=100*X     ' change the build in
  Print Cos(3), @Cos(3)  ' @Cos() is the build in anyway
  ' we can't use simple function with same name as a bultin function.
//  Distinguishing subroutines and functions
  Name without parenthesis like a command or statement is a Module
  Name with parentesis without operator is a Sub
  Name with parenthesis in an expression is a function or array (array come first), using a(*10) we say that it is function even an array a() exist.
  Name with @ as first symbol and parenthesis like @alfa() is a simple function unless has a builtin name, so is that function.
//  Stating whether arguments are passed by value or by reference
    Default:By Value
    By Reference: Using & at both sides (caller and calee)
    Function Alfa(&x) {
	=X : X++
    }
    Print Alfa(&counter)
    Subs and Simple Functions not need a by reference pass because they are in the same scope from the caller, so actuall we pass by value to be local to those entities. But we can use by reference, except for static variables, and array items. Those can only passed by reference on modules and nornal functions and lambdas (which are normal functions plus more).

//  Is partial application possible and how
A=Lambda (X) -> {
	=Lambda X (Y) -> {
		=Y**X
	}
}
Cube=A(3) : Square=A(2)
Print Cube(2)=8, Square(2)=4

OOP: Functions/Modules can be members of objects.
Objects may have a name (they live until code get out of scope)
Objects may don't have a name but one or more pointers, (they live until counting references are zero)

  ObjectA.moduleA  is a call to an object method (a module)
  pointerA=>moduleA is a call to an object by a pointer

An object may return values, and may accept parameters too. Also objects if they didn't return values other than a copy of them can be use operators defined as object functions.

Objects may have events and fire them using Call Event "simpleevent", param1, param2...

Functions and lambda (not simple functions), and object functions can be passed by reference as parameters.


    % Calling a function that requires no arguments
       function a=foo();
         a=4;
       end;
       x = foo();
    % Calling a function with a fixed number of arguments
       function foo(a,b,c);
         %% function definition;
       end;
       foo(x,y,z);
    % Calling a function with optional arguments
       function foo(a,b,c);
	if nargin<2, b=0; end;
	if nargin<3, c=0; end;
         %% function definition;
       end;
       foo(x,y);
    % Calling a function with a variable number of arguments
       function foo(varargin);
	  for k=1:length(varargin)
            arg{k} = varargin{k};
       end;
       foo(x,y);
    % Calling a function with named arguments
	%% does not apply
    % Using a function in statement context
	%% does not apply
    % Using a function in first-class context within an expression
    % Obtaining the return value of a function
       function [a,b]=foo();
         a=4;
         b='result string';
       end;
       [x,y] = foo();
    % Distinguishing built-in functions and user-defined functions
	fun = 'foo';
	if (exist(fun,'builtin'))
 		printf('function %s is a builtin\n');
        elseif (exist(fun,'file'))
 		printf('function %s is user-defined\n');
        elseif (exist(fun,'var'))
 		printf('function %s is a variable\n');
        else
 		printf('%s is not a function or variable.\n');
        end
    % Distinguishing subroutines and functions
        % there are only scripts and functions, any function declaration starts with the keyword function, otherwise it is a script that runs in the workspace
    % Stating whether arguments are passed by value or by reference
      % arguments are passed by value, however Matlab has delayed evaluation, such that a copy of large data structures are done only when an element is written to.


// function with no arguments
no_args()

// function with fixed amount of arguments
three_args(a, b, c)

// nanoquery does not support optional, variable, or named arguments

// obtaining a return value
value = returns_value()

// checking if a function called "func" is user-defined
try
        type(func)
        println "func is user-defined"
catch
        println "func is a built-in or doesn't exist"
end


// no arguments
f()

// fixed arguments
def f(a, b) { ... } // as an aside, functions defined with 'def' use type inference for parameters and return types
f(1, 'a')

// optional arguments
def f(a, b = 0) { ... }
f("hello")
f("goodbye", 2)
f("hey", b = 2) // using the name makes more sense if there's more than one optional argument, obviously

// variable number of arguments
def f(params args) { ... }
def g(a, b, params rest) { ... }
f(1, 2, 3) // arguments should all have the same type or may be coerced to a supertype
g(1.0, 2, "a", "hello")

// named arguments
f(a = 'a', b = 0)
f(b = 0, a = 'a')
f('a', b = 0) // if mixing named and unnamed args, unnamed must be first and in correct order

// statement context
if (f(foo) == 42)
    WriteLine($"$foo is the meaning to life, the universe and everything.")
else WriteLine($"$foo is meaningless.")

// first class function in an expression
def a = numList.FoldLeft(f)

// obtaining return value
def a = f(3)

// distinguishing built-in from user functions
//   N/A?

// distinguishing subroutines from functions
//   N/A

// stating whether passed by value or by reference
//   .NET distinguishes between value types and reference types; if a reference type is passed by reference (using ref or out),
//   the reference is passed by reference, which would allow a method to modify the object to which the reference refers
def f(a, ref b) { ... }
mutable someVar = "hey there" // doesn't make sense to pass immutable value by ref
f(2, ref someVar)
def g(a, out b) { ... }
mutable someOtherVar // if passed by ref using 'out', the variable needn't be initialized
g(2, out someOtherVar)

// partial application
def f(a, b) { ... }
def g = f(2, _)
def h = f(_, 2)
def a = g(3) // equivalent to: def a = f(2, 3)
def b = h(3) // equivalent to: def b = f(3, 2)


proc no_args() =
  discard
# call
no_args()

proc fixed_args(x, y) =
  echo x
  echo y
# calls
fixed_args(1, 2)        # x=1, y=2
fixed_args 1, 2         # same call
1.fixed_args(2)         # same call

proc opt_args(x=1.0) =
  echo x
# calls
opt_args()              # 1
opt_args(3.141)         # 3.141

proc var_args(v: varargs[string, `$`]) =
  for x in v: echo x
# calls
var_args(1, 2, 3)       # (1, 2, 3)
var_args(1, (2,3))      # (1, (2, 3))
var_args()              # ()

## Named arguments
fixed_args(y=2, x=1)    # x=1, y=2

## As a statement
if true:
  no_args()

proc return_something(x): int =
  x + 1

var a = return_something(2)

## First-class within an expression
let x = return_something(19) + 10
let y = 19.return_something() + 10
let z = 19.return_something + 10


; note: sign "==>" indicates expected output

;;; Calling a function that requires no arguments
(define (no-args-function)
   (print "ok."))

(no-args-function)
; ==> ok.

;;; Calling a function with a fixed number of arguments
(define (two-args-function a b)
   (print "a: " a)
   (print "b: " b))

(two-args-function 8 13)
; ==> a: 8
; ==> b: 13

;;; Calling a function with optional arguments
(define (optional-args-function a . args)
   (print "a: " a)
   (if (null? args)
      (print "no optional arguments"))
   (if (less? 0 (length args))
      (print "b: " (car args)))
   (if (less? 1 (length args))
      (print "c: " (cadr args)))
   ; etc...
)

(optional-args-function 3)
; ==> a: 3
; ==> no optional arguments
(optional-args-function 3 8)
; ==> a: 3
; ==> b: 8
(optional-args-function 3 8 13)
; ==> a: 3
; ==> b: 8
; ==> c: 13
(optional-args-function 3 8 13 77)
; ==> a: 3
; ==> b: 8
; ==> c: 13

;;; Calling a function with a variable number of arguments
; /same as optional arguments

;;; Calling a function with named arguments
; /no named arguments "from the box" is provided, but it can be easily simulated using builtin associative arrays (named "ff")
(define (named-args-function args)
   (print "a: " (get args 'a 8)) ; 8 is default value if no variable value given
   (print "b: " (get args 'b 13)); same as above
)

(named-args-function #empty)
; ==> a: 8
; ==> b: 13
(named-args-function (list->ff '((a . 3))))
; ==> a: 3
; ==> b: 13
; or nicer (and shorter) form available from ol version 2.1
(named-args-function '{a 3})
; ==> a: 3
; ==> b: 13
(named-args-function '{b 7})
; ==> a: 8
; ==> b: 7
(named-args-function '{a 3  b 7})
; ==> a: 3
; ==> b: 7

;;; Using a function in first-class context within an expression
(define (first-class-arg-function arg a b)
   (print (arg a b))
)

(first-class-arg-function + 2 3)
; ==> 5
(first-class-arg-function - 2 3)
; ==> -1

;;; Using a function in statement context
(let ((function (lambda (x) (* x x))))
   (print (function 4))
; ==> 16
;(print (function 4))
; ==> What is 'function'?

;;; Obtaining the return value of a function
(define (return-value-function)
   (print "ok.")
   123)

(let ((result (return-value-function)))
   (print result))
; ==> ok.
; ==> 123

;;; Obtaining the return value of a function while breaking the function execution (for example infinite loop)
(print
   (call/cc (lambda (return)
      (let loop ((n 0))
         (if (eq? n 100)
            (return (* n n)))
         (loop (+ n 1))))))) ; this is infinite loop
; ==> 10000

;;; Is partial application possible and how
(define (make-partial-function n)
   (lambda (x y)
      (print (n x y)))
)

(define plus (make-partial-function +))
(define minus (make-partial-function -))

(plus 2 3)
; ==> 5
(minus 2 3)
; ==> -1

;;; Distinguishing built-in functions and user-defined functions
; ol has no builtin functions but only eight builtin forms: quote, values, lambda, setq, letq, ifeq, either, values-apply.
; all other functions is "user-defined", and some of them defined in base library, for example (scheme core) defines if, or, and, zero?, length, append...

;;; Distinguishing subroutines and functions
; Both subroutines and functions is a functions in Ol.
; Btw, the "subroutine" has a different meaning in Ol - the special function that executes simultaneously in own context. The intersubroutine messaging mechanism is provided, sure.

;;; Stating whether arguments are passed by value or by reference
; The values in Ol always passed as values and objects always passed as references. If you want to pass an object copy - make a copy by yourself.


say 'DATE'()
Say date()
Exit
daTe: Return 'my date'


f(); \\ zero arguments
sin(Pi/2); \\ fixed number of arguments
vecsort([5,6]) != vecsort([5,6],,4) \\ optional arguments
Str("gg", 1, "hh") \\ variable number of arguments
call(Str, ["gg", 1, "hh"]) \\ variable number of arguments in a vector
(x->x^2)(3); \\ first-class
x = sin(0); \\ get function value


foo();              # Call foo on the null list
&foo();             # Ditto
foo($arg1, $arg2);  # Call foo on $arg1 and $arg2
&foo($arg1, $arg2); # Ditto; ignores prototypes


def saludo
    "Hola mundo" print nl
enddef

saludo

getid saludo exec


Procedure Saludo()
  PrintN("Hola mundo!")
EndProcedure

Procedure.s Copialo(txt.s, siNo.b, final.s = "")
  Define nuevaCadena.s, resul.s

  For cont.b = 1 To siNo
    nuevaCadena + txt
  Next

  Resul = Trim(nuevaCadena) + final

  ProcedureReturn resul
EndProcedure

Procedure testNumeros(a.i, b.i, c.i = 0)
  PrintN(Str(a) + #TAB$ + Str(b) + #TAB$ + Str(c))
EndProcedure

Procedure testCadenas(txt.s)
  For cont.b = 1 To Len(txt)
    Print(Mid(txt,cont,1))
  Next cont
EndProcedure

OpenConsole()
Saludo()
PrintN(Copialo("Saludos ", 6))
PrintN(Copialo("Saludos ", 3, "!!"))
PrintN("")
testNumeros(1, 2, 3)
testNumeros(1, 2)
PrintN("")
testCadenas("1, 2, 3, 4, cadena, 6, 7, 8, \'incluye texto\'")

Input()
CloseConsole()


def no_args():
    pass
# call
no_args()

def fixed_args(x, y):
    print('x=%r, y=%r' % (x, y))
# call
fixed_args(1, 2)        # x=1, y=2

## Can also called them using the parameter names, in either order:
fixed_args(y=2, x=1)

## Can also "apply" fixed_args() to a sequence:
myargs=(1,2) # tuple
fixed_args(*myargs)

def opt_args(x=1):
    print(x)
# calls
opt_args()              # 1
opt_args(3.141)         # 3.141

def var_args(*v):
    print(v)
# calls
var_args(1, 2, 3)       # (1, 2, 3)
var_args(1, (2,3))      # (1, (2, 3))
var_args()              # ()

## Named arguments
fixed_args(y=2, x=1)    # x=1, y=2

## As a statement
if 1:
    no_args()

## First-class within an expression
assert no_args() is None

def return_something():
    return 1
x = return_something()

def is_builtin(x):
	print(x.__name__ in dir(__builtins__))
# calls
is_builtin(pow)         # True
is_builtin(is_builtin)  # False

# Very liberal function definition

def takes_anything(*args, **kwargs):
    for each in args:
        print(each)
    for key, value in sorted(kwargs.items()):
        print("%s:%s" % (key, value))
    # Passing those to another, wrapped, function:
    wrapped_fn(*args, **kwargs)
    # (Function being wrapped can have any parameter list
    # ... that doesn't have to match this prototype)

## A subroutine is merely a function that has no explicit
## return statement and will return None.

## Python uses "Call by Object Reference".
## See, for example, http://www.python-course.eu/passing_arguments.php

## For partial function application see:
##   http://rosettacode.org/wiki/Partial_function_application#Python


FUNCTION Copialo$ (txt$, siNo, final$)
    DIM nuevaCadena$

    FOR cont = 1 TO siNo
	nuevaCadena$ = nuevaCadena$ + txt$
    NEXT cont

    Copialo$ = LTRIM$(RTRIM$(nuevaCadena$)) + final$
END FUNCTION

SUB Saludo
    PRINT "Hola mundo!"
END SUB

SUB testCadenas (txt$)
    FOR cont = 1 TO LEN(txt$)
	PRINT MID$(txt$, cont, 1); "";
    NEXT cont
END SUB

SUB testNumeros (a, b, c)
	PRINT a, b, c
END SUB

CALL Saludo
PRINT Copialo$("Saludos ", 6, "")
PRINT Copialo$("Saludos ", 3, "!!")
PRINT
CALL testNumeros(1, 2, 3)
CALL testNumeros(1, 2, 0)
PRINT
CALL testCadenas("1, 2, 3, 4, cadena, 6, 7, 8, \'incluye texto\'")


### Calling a function that requires no arguments
no_args <- function() NULL
no_args()

### Calling a function with a fixed number of arguments
fixed_args <- function(x, y) print(paste("x=", x, ", y=", y, sep=""))
fixed_args(1, 2)        # x=1, y=2
fixed_args(y=2, x=1)    # y=1, x=2

### Calling a function with optional arguments
opt_args <- function(x=1) x
opt_args()              # x=1
opt_args(3.141)         # x=3.141

### Calling a function with a variable number of arguments
var_args <- function(...) print(list(...))
var_args(1, 2, 3)
var_args(1, c(2,3))
var_args()

### Calling a function with named arguments
fixed_args(y=2, x=1)    # x=1, y=2

### Using a function in statement context
if (TRUE) no_args()

### Using a function in first-class context within an expression
print(no_args)

### Obtaining the return value of a function
return_something <- function() 1
x <- return_something()
x

### Distinguishing built-in functions and user-defined functions
# Not easily possible. See
# http://cran.r-project.org/doc/manuals/R-ints.html#g_t_002eInternal-vs-_002ePrimitive
# for details.

### Distinguishing subroutines and functions
# No such distinction.

### Stating whether arguments are passed by value or by reference
# Pass by value.

### Is partial application possible and how
# Yes, see http://rosettacode.org/wiki/Partial_function_application#R


#lang racket

;; Calling a function that requires no arguments
(foo)

;; Calling a function with a fixed number of arguments
(foo 1 2 3)

;; Calling a function with optional arguments
;; Calling a function with a variable number of arguments
(foo 1 2 3) ; same in both cases

;; Calling a function with named arguments
(foo 1 2 #:x 3) ; using #:keywords for the names

;; Using a function in statement context
;; Using a function in first-class context within an expression
;; Obtaining the return value of a function
;; -> Makes no sense for Racket, as well as most other functional PLs

;; Distinguishing built-in functions and user-defined functions
(primitive? foo)
;; but this is mostly useless, since most of Racket is implemented in
;; itself

;; Distinguishing subroutines and functions
;; -> No difference, though `!' is an idiomatic suffix for names of
;;    side-effect functions, and they usually return (void)

;; Stating whether arguments are passed by value or by reference

;; -> Always by value, but it's possible to implement languages with
;;    other argument passing styles, including passing arguments by
;;    reference (eg, there is "#lang algol60")

;; Is partial application possible and how
(curry foo 1 2)    ; later apply this on 3
(λ(x) (foo 1 2 x)) ; a direct way of doing the same


foo               # as list operator
foo()             # as function
foo.()            # as function, explicit postfix form
$ref()            # as object invocation
$ref.()           # as object invocation, explicit postfix
&foo()            # as object invocation
&foo.()           # as object invocation, explicit postfix
::($name)()       # as symbolic ref


/*REXX pgms demonstrates various methods/approaches of invoking/calling a REXX function.*/

                /*╔════════════════════════════════════════════════════════════════════╗
                  ║ Calling a function that REQUIRES no arguments.                     ║
                  ║                                                                    ║
                  ║ In the REXX language, there is no way to require the caller to not ║
                  ║ pass arguments, but the programmer can check if any arguments were ║
                  ║ (or weren't) passed.                                               ║
                  ╚════════════════════════════════════════════════════════════════════╝*/

yr= yearFunc()                              /*the function name is caseless if it isn't */
                                            /*enclosed in quotes (') or apostrophes (").*/
say 'year='  yr
exit                                             /*stick a fork in it,  we're all done. */

yearFunc: procedure                              /*function  ARG  returns the # of args.*/
          errmsg= '***error***'                  /*an error message eyecatcher string.  */
          if arg() \== 0  then say errmsg  "the YEARFUNC function won't accept arguments."
          return left( date('Sorted'), 3)


hello()
func hello
        see "Hello from function" + nl


fn main() {
    // Rust has a lot of neat things you can do with functions: let's go over the basics first
    fn no_args() {}
    // Run function with no arguments
    no_args();

    // Calling a function with fixed number of arguments.
    // adds_one takes a 32-bit signed integer and returns a 32-bit signed integer
    fn adds_one(num: i32) -> i32 {
        // the final expression is used as the return value, though `return` may be used for early returns
        num + 1
    }
    adds_one(1);

    // Optional arguments
    // The language itself does not support optional arguments, however, you can take advantage of
    // Rust's algebraic types for this purpose
    fn prints_argument(maybe: Option<i32>) {
        match maybe {
            Some(num) => println!("{}", num),
            None => println!("No value given"),
        };
    }
    prints_argument(Some(3));
    prints_argument(None);

    // You could make this a bit more ergonomic by using Rust's Into trait
    fn prints_argument_into<I>(maybe: I)
        where I: Into<Option<i32>>
    {
        match maybe.into() {
            Some(num) => println!("{}", num),
            None => println!("No value given"),
        };
    }
    prints_argument_into(3);
    prints_argument_into(None);

    // Rust does not support functions with variable numbers of arguments. Macros fill this niche
    // (println! as used above is a macro for example)

    // Rust does not support named arguments

    // We used the no_args function above in a no-statement context

    // Using a function in an expression context
    adds_one(1) + adds_one(5); // evaluates to eight

    // Obtain the return value of a function.
    let two = adds_one(1);

    // In Rust there are no real built-in functions (save compiler intrinsics but these must be
    // manually imported)

    // In rust there are no such thing as subroutines

    // In Rust, there are three ways to pass an object to a function each of which have very important
    // distinctions when it comes to Rust's ownership model and move semantics. We may pass by
    // value, by immutable reference, or mutable reference.

    let mut v = vec![1, 2, 3, 4, 5, 6];

    // By mutable reference
    fn add_one_to_first_element(vector: &mut Vec<i32>) {
        vector[0] += 1;
    }
    add_one_to_first_element(&mut v);
    // By immutable reference
    fn print_first_element(vector: &Vec<i32>) {
        println!("{}", vector[0]);
    }
    print_first_element(&v);

    // By value
    fn consume_vector(vector: Vec<i32>) {
        // We can do whatever we want to vector here
    }
    consume_vector(v);
    // Due to Rust's move semantics, v is now inaccessible because it was moved into consume_vector
    // and was then dropped when it went out of scope

    // Partial application is not possible in rust without wrapping the function in another
    // function/closure e.g.:
    fn average(x: f64, y: f64) -> f64 {
        (x + y) / 2.0
    }
    let average_with_four = |y| average(4.0, y);
    average_with_four(2.0);

}


def ??? = throw new NotImplementedError // placeholder for implementation of hypothetical methods
def myFunction0() = ???
myFunction0() // function invoked with empty parameter list
myFunction0   // function invoked with empty parameter list omitted

def myFunction = ???
myFunction          // function invoked with no arguments or empty arg list
/* myFunction() */  // error: does not take parameters

def myFunction1(x: String) = ???
myFunction1("foobar")     // function invoked with single argument
myFunction1 { "foobar" }  // function invoked with single argument provided by a block
                          // (a block of code within {}'s' evaluates to the result of its last expression)

def myFunction2(first: Int, second: String) = ???
val b = "foobar"
myFunction2(6, b) // function with two arguments

def multipleArgLists(first: Int)(second: Int, third: String) = ???
multipleArgLists(42)(17, "foobar")  // function with three arguments in two argument lists

def myOptionalParam(required: Int, optional: Int = 42) = ???
myOptionalParam(1)    // function with optional param
myOptionalParam(1, 2) // function with optional param provided

def allParamsOptional(firstOpt: Int = 42, secondOpt: String = "foobar") = ???
allParamsOptional()     // function with all optional args
/* allParamsOptional */ // error: missing arguments for method allParamsOptional;
                        //        follow with `_' if you want to treat it as a partially applied function

def sum[Int](values: Int*) = values.foldLeft(0)((a, b) => a + b)
sum(1, 2, 3)                // function accepting variable arguments as literal

val values = List(1, 2, 3)
sum(values: _*)             // function acception variable arguments from collection
sum()                       // function accepting empty variable arguments

def mult(firstValue: Int, otherValues: Int*) = otherValues.foldLeft(firstValue)((a, b) => a * b)
mult(1, 2, 3)                             // function with non-empty variable arguments
myOptionalParam(required = 1)             // function called with named arguments (all functions have named arguments)
myFunction2(second = "foo", first = 1)    // function with re-ordered named arguments
mult(firstValue = 1, otherValues = 2, 3)  // function with named variable argument as literal

val otherValues = Seq(2, 3)
mult(1, otherValues = otherValues: _*)  // function with named variable argument from collection
val result = myFunction0()              // function called in an expression context
myFunction0()                           // function called in statement context
/* myOptionalParam(optional = 1, 2) */  // error: positional after named argument.

def transform[In, Out](initial: In)(transformation: In => Out) = transformation(initial)
val result = transform(42)(x => x * x)  // function in first-class context within an expression

def divide(top: Double, bottom: Double) = top / bottom
val div = (divide _)              // partial application -- defer application of entire arg list
val halve = divide(_: Double, 2)  // partial application -- defer application of some arguments

class Foo(var value: Int)
def incFoo(foo: Foo) = foo.value += 1 // function showing AnyRef's are passed by reference
/* def incInt(i: Int) = i += 1 */     // error: += is not a member of Int
                                      // (All arguments are passed by reference, but reassignment
                                      // or setter must be defined on a type or a field
                                      // (respectively) in order to modify its value.)

// No distinction between built-in functions and user-defined functions
// No distinction between subroutines and functions


put zeroArgsFn()

// Function calls can also be made using the following syntax:
put the zeroArgsFn

function zeroArgsFn
    put "This function was run with zero arguments."
    return "Return value from zero argument function"
end zeroArgsFn


foo();                       # without arguments
foo(1, 2);                   # with two arguments
foo(args...);                # with a variable number of arguments
foo(name: 'Bar', age: 42);   # with named arguments

var f = foo;                 # store the function foo inside 'f'
var result = f();            # obtain the return value of a function

var arr = [1,2,3];
foo(arr);                    # the arguments are passed by object-reference


// call a function with no args
noArgs()

// call a function with one arg with no external name
oneArgUnnamed(1)

// call a function with one arg with external name
oneArgNamed(arg: 1)

// call a function with two args with no external names
twoArgsUnnamed(1, 2)

// call a function with two args and external names
twoArgsNamed(arg1: 1, arg2: 2)

// call a function with an optional arg
// with arg
optionalArguments(arg: 1)
// without
optionalArguments() // defaults to 0

// function that takes another function as arg
funcArg(noArgs)

// variadic function
variadic(opts: "foo", "bar")

// getting a return value
let foo = returnString()

// getting a bunch of return values
let (foo, bar, baz) = returnSomeValues()

// getting a bunch of return values, discarding second returned value
let (foo, _, baz) = returnSomeValues()


aCallToACommandWithNoArguments
aCallToACommandWithOne argument
aCallToACommandWith arbitrarily many arguments
aCallToACommandWith {*}$manyArgumentsComingFromAListInAVariable
aCallToACommandWith -oneNamed argument -andAnother namedArgument
aCallToACommandWith theNameOfAnotherCommand
aCallToOneCommand [withTheResultOfAnother]


FUNCTION Copialo$ (txt$, siNo, final$)
    FOR cont = 1 TO ROUND(siNo)
        LET nuevaCadena$ = nuevaCadena$ & txt$
    NEXT cont

    LET Copialo$ = LTRIM$(RTRIM$(nuevaCadena$)) & final$
END FUNCTION

SUB Saludo
    PRINT "Hola mundo!"
END SUB

SUB testCadenas (txt$)
    FOR cont = 1 TO ROUND(LEN(txt$))
        PRINT (txt$)[cont:cont+1-1]; "";
    NEXT cont
END SUB

SUB testNumeros (a, b, c)
    PRINT a, b, c
END SUB

CALL Saludo
PRINT Copialo$("Saludos ", 6, "")
PRINT Copialo$("Saludos ", 3, "!  !")
PRINT
CALL testNumeros(1, 2, 3)
CALL testNumeros(1, 2, 0)
PRINT
CALL testCadenas("1, 2, 3, 4, cadena, 6, 7, 8, \'incluye texto\'")
END


sayhello    # Call a function in statement context with no arguments
multiply 3 4    # Call a function in statement context with two arguments


'definitions/declarations

'Calling a function that requires no arguments
Function no_arguments() As String
    no_arguments = "ok"
End Function

'Calling a function with a fixed number of arguments
Function fixed_number(argument1 As Integer, argument2 As Integer)
    fixed_number = argument1 + argument2
End Function

'Calling a function with optional arguments
Function optional_parameter(Optional argument1 = 1) As Integer
    'Optional parameters come at the end of the parameter list
    optional_parameter = argument1
End Function

'Calling a function with a variable number of arguments
Function variable_number(arguments As Variant) As Integer
    variable_number = UBound(arguments)
End Function

'Calling a function with named arguments
Function named_arguments(argument1 As Integer, argument2 As Integer) As Integer
    named_arguments = argument1 + argument2
End Function

'Using a function in statement context
Function statement() As String
    Debug.Print "function called as statement"
    statement = "ok"
End Function

'Using a function in first-class context within an expression
'see call the functions

'Obtaining the return value of a function
Function return_value() As String
    return_value = "ok"
End Function

'Distinguishing built-in functions and user-defined functions
'There is no way to distinguish built-in function and user-defined functions

'Distinguishing subroutines And functions
'subroutines are declared with the reserved word "sub" and have no return value
Sub foo()
    Debug.Print "subroutine",
End Sub
'functions are declared with the reserved word "function" and can have a return value
Function bar() As String
    bar = "function"
End Function

'Stating whether arguments are passed by value or by reference
Function passed_by_value(ByVal s As String) As String
    s = "written over"
    passed_by_value = "passed by value"
End Function
'By default, parameters in VBA are by reference
Function passed_by_reference(ByRef s As String) As String
    s = "written over"
    passed_by_reference = "passed by reference"
End Function

'Is partial application possible and how
'I don't know

'calling a subroutine with arguments does not require parentheses
Sub no_parentheses(myargument As String)
    Debug.Print myargument,
End Sub

'call the functions
Public Sub calling_a_function()
    'Calling a function that requires no arguments
    Debug.Print "no arguments", , no_arguments
    Debug.Print "no arguments", , no_arguments()
    'Parentheses are not required

    'Calling a function with a fixed number of arguments
    Debug.Print "fixed_number", , fixed_number(1, 1)

    'Calling a function with optional arguments
    Debug.Print "optional parameter", optional_parameter
    Debug.Print "optional parameter", optional_parameter(2)

    'Calling a function with a variable number of arguments
    Debug.Print "variable number", variable_number([{"hello", "there"}])
    'The variable number of arguments have to be passed as an array

    'Calling a function with named arguments
    Debug.Print "named arguments", named_arguments(argument2:=1, argument1:=1)

    'Using a function in statement context
    statement

    'Using a function in first-class context within an expression
    s = "no_arguments"
    Debug.Print "first-class context", Application.Run(s)
    'A function name can be passed as argument in a string

    'Obtaining the return value of a function
    returnvalue = return_value
    Debug.Print "obtained return value", returnvalue

    'Distinguishing built-in functions and user-defined functions

    'Distinguishing subroutines And functions
    foo
    Debug.Print , bar

    'Stating whether arguments are passed by value or by reference
    Dim t As String
    t = "unaltered"
    Debug.Print passed_by_value(t), t
    Debug.Print passed_by_reference(t), t

    'Is partial application possible and how
    'I don 't know

    'calling a subroutine with arguments does not require parentheses
    no_parentheses "calling a subroutine"
    Debug.Print "does not require parentheses"
    Call no_parentheses("deprecated use")
    Debug.Print "of parentheses"

End Sub


let noargs => + 2 5;
noargs -- print;

let fixedargs a b => + a b;
fixedargs 3 5 -- print;

let m => import 'math';
m.cos 3 -- print;

# WDTE only has expressions, not statements, so statement vs.
# first-class context doesn't make sense.

# Arguments in WDTE are technically passed by reference, in a way, but
# because it's a functional language and everything's immutable
# there's no real usability difference from that.

# Partial application is possible. For example, the following
# evaluates `+ 3` and then passes 7 to the resulting partially applied
# function.
(+ 3) 7 -- print;


(func $main (export "_start")

    (local $result i32)

    ;;Call a function with no arguments
    call $noargfunc

    ;;Multiply two numbers and store the result, flat syntax
    i32.const 12
    i32.const 3
    call $multipy
    set_local $result

    ;;Multiply two numbers and store the result, indented syntax
    (set_local $result
        (call $multipy
            (i32.const 12)
            (i32.const 3)
        )
    )

    ;;Add two numbers in linear memory (similar to using pointers)
    (i32.store (i32.const 0) (i32.const 5))
    (i32.store (i32.const 4) (i32.const 7))

    (call $addinmemory
        (i32.const 0)
        (i32.const 4)
        (i32.const 8)
    )
)


var f1 = Fn.new { System.print("Function 'f1' with no arguments called.") }
var f2 = Fn.new { |a, b|
    System.print("Function 'f2' with 2 arguments called and passed %(a) & %(b).")
}
var f3 = Fn.new { 42 }  // function which returns a concrete value

f1.call()               // statement context
f2.call(2, 3)           // ditto
var v1 = 8 + f3.call()  // calling function within an expression
var v2 = f3.call()      // obtaining return value
System.print([v1, v2])  // print last two results as a list

class MyClass {
    static m() { System.print("Static method 'm' called.") }

    construct new(x) { _x = x  } // stores 'x' in a field

    x { _x }          // gets the field
    x=(y) { _x = y }  // sets the field to 'y'

    - { MyClass.new(-_x) }         // prefix operator
    +(o) { MyClass.new(_x + o.x) } // infix operator

    toString { _x.toString } // instance method
}

MyClass.m()               // call static method 'm'
var mc1 = MyClass.new(40) // construct 'mc1'
var mc2 = MyClass.new(8)  // construct 'mc2'
System.print(mc1.x)       // print mc1's field using getter
mc1.x = 42                // change mc1's field using setter
System.print(-mc1.x)      // invoke prefix operator -
System.print(mc1 + mc2)   // invoke infix operator +


; call a function (procedure) with no arguments:
(foo)

; call a function (procedure) with arguments:
(foo bar baz)
; the first symbol after "(" is the name of the function
; the other symbols are the arguments

; call a function on a list of arguments formed at run time:
(apply foo bar)

; In a REPL, the return value will be printed.
; In other contexts, it can be fed as argument into a further function:
(foo (bar baz))
; this calls bar on the argument baz and then calls foo on the return value

; or it can simply be discarded
(foo bar)
; nothing is done with the return value


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/">
        <demo>
            <!--
                XSLT 1.0 actually defines two function-like constructs that
                are used variously depending on the context.
            -->
            <xsl:call-template name="xpath-function-demos"/>
            <xsl:call-template name="xslt-template-demos"/>
        </demo>
    </xsl:template>

    <xsl:template name="xpath-function-demos">
        <!--
            A 'function' in XSLT 1.0 is a function that can be called from
            an XPath 1.0 expression (such as from "select" or "test"
            attribute of several XSLT elements). The following demos apply
            to these functions.
        -->

        <!-- Calling function that requires no arguments -->
        <!-- false() always returns a boolean false value -->
        <line>This test is <xsl:if test="false()">NOT</xsl:if> OK.</line>

        <!-- Calling a function with a fixed number of arguments -->
        <!-- not() takes exactly 1 argument. starts-with() takes exactly 2 arguments. -->
        <line>'haystack' does <xsl:if test="not(starts-with('haystack', 'hay'))">NOT</xsl:if> start with 'hay'.</line>

        <!-- Calling a function with optional arguments -->
        <!-- If the third argument of substring() is omitted, the length of the string is assumed. -->
        <line>'<xsl:value-of select="substring('haystack', 1, 3)"/>' = 'hay'</line>
        <line>'<xsl:value-of select="substring('haystack', 4)"/>' = 'stack'</line>

        <!-- Calling a function with a variable number of arguments -->
        <!-- concat() accepts two or more arguments. -->
        <line>'<xsl:value-of select="concat('abcd', 'efgh')"/>' = 'abcdefgh'</line>
        <line>'<xsl:value-of select="concat('ij', 'kl', 'mn', 'op')"/>' = 'ijklmnop'</line>
        <!--
            Aggregate functions such as sum() and count() accept nodesets.
            This isn't quite the same as varargs but are probably worth
            mentioning.
        -->
        <line>The number of root elements in the input document is <xsl:value-of select="count(/*)"/> (should be 1).</line>

        <!-- Calling a function with named arguments -->
        <!-- XPath 1.0 uses only positional parameters. -->

        <!-- Using a function in statement context -->
        <!--
            In general, XPath 1.0 functions have no side effects, so calling
            them as statements is useless. While implementations often allow
            writing extensions in imperative languages, the semantics of
            calling a function with side effects are, at the very least,
            implementation-dependent.
        -->

        <!-- Using a function in first-class context within an expression -->
        <!-- Functions are not natively first-class values in XPath 1.0. -->

        <!-- Obtaining the return value of a function -->
        <!--
            The return value of the function is handled as specified by the
            various contexts in which an XPath expression is used. The
            return value can be stored in a "variable" (no destructive
            assignment is allowed), passed as a parameter to a function or a
            template, used as a conditional in an <xsl:if/> or <xsl:when/>,
            interpolated into text using <xsl:value-of/> or into an
            attribute value using brace syntax, and so forth.
        -->
        <!-- Here, concat() is interpolated into an attribute value using braces ({}). -->
        <line foo="{concat('Hello, ', 'Hello, ', 'Hello')}!">See attribute.</line>

        <!-- Distinguishing built-in functions and user-defined functions -->
        <!--
            Given that functions aren't first-class here, the origin of any
            given function is known before run time. Incidentally, functions
            defined by the standard are generally unprefixed while
            implementation-specific extensions (and user extensions, if
            available) must be defined within a separate namespace and
            prefixed.
        -->

        <!-- Distinguishing subroutines and functions -->
        <!--
            There are no "subroutines" in this sense—everything that looks
            like a subroutine has some sort of return or result value.
        -->

        <!-- Stating whether arguments are passed by value or by reference -->
        <!-- There is no meaningful distinction since there is no mechanism by which to mutate values. -->

        <!-- Is partial application possible and how -->
        <!-- Not natively. -->
    </xsl:template>

    <xsl:template name="xslt-template-demos">
        <!--
            A 'template' in XSLT 1.0 is a subroutine-like construct. When
            given a name (and, optionally, parameters), it can be called
            from within another template using the <xsl:call-template/>
            element. (An unnamed template is instead called according to its
            match and mode attributes.) The following demos apply to named
            templates.
        -->
        <!--
            Unlike with functions, there are no built-in named templates to
            speak of. The ones used here are defined later in this
            transform.
        -->

        <!--
            Answers for these prompts are the same as with XPath functions (above):
                Using a function in statement context
                Distinguishing subroutines and functions
                Stating whether arguments are passed by value or by reference
                Is partial application possible and how
        -->

        <!-- Calling function that requires no arguments -->
        <xsl:call-template name="nullary-demo"/>
        <!--
            Note that even if a template has no parameters, it has access to
            the current node (.) as of the time of the call. This
            <xsl:apply-templates/> runs a matching template above that calls
            the template "nullary-context-demo" with no parameters. Another
            way to manipulate a template's idea of which node is current is
            by calling from inside a <xsl:for-each/> loop.
        -->
        <xsl:apply-templates select="/*" mode="nullary-context-demo-mode"/>

        <!--
            A template parameter is made optional in the definition of the
            template by supplying an expression as its select attribute,
            which is evaluated and used as its value if the parameter is
            omitted. Note, though, that all template parameters have an
            implicit default value, the empty string, if the select
            attribute is not specified. Therefore, all template parameters
            are always optional, even when semantically they should not be.
        -->

        <!-- Calling a function with a fixed number of arguments -->
        <working note="When all parameters are supplied">
            <xsl:call-template name="ternary-demo">
                <xsl:with-param name="a" select="4"/>
                <xsl:with-param name="b">3</xsl:with-param>
                <xsl:with-param name="c" select="2 + 3"/>
            </xsl:call-template>
        </working>
        <broken note="When the third parameter 'c' is omitted">
            <xsl:call-template name="ternary-demo">
                <xsl:with-param name="a" select="4"/>
                <xsl:with-param name="b">3</xsl:with-param>
            </xsl:call-template>
        </broken>

        <!-- Calling a function with optional arguments -->
        <!-- With the optional third parameter -->
        <working name="When all parameters are supplied">
            <xsl:call-template name="binary-or-ternary-demo">
                <xsl:with-param name="a" select="4"/>
                <xsl:with-param name="b" select="3"/>
                <xsl:with-param name="c" select="5"/>
            </xsl:call-template>
        </working>
        <!-- Without the optional third parameter (which defaults to 0) -->
        <working name="When 'a' and 'b' are supplied but 'c' is defaulted to 0">
            <xsl:call-template name="binary-or-ternary-demo">
                <xsl:with-param name="a" select="4"/>
                <xsl:with-param name="b" select="3"/>
            </xsl:call-template>
        </working>

        <!-- Calling a function with a variable number of arguments -->
        <!--
            Templates are not varargs-capable. Variable numbers of arguments
            usually appear in the form of a nodeset which is then bound to a
            single parameter name.
        -->

        <!-- Calling a function with named arguments -->
        <!--
            Other than what comes with the current context, template
            arguments are always named and can be supplied in any order.
            Templates do not support positional arguments. Additionally,
            even arguments not specified by the template may be passed; they
            are silently ignored.
        -->

        <!-- Using a function in first-class context within an expression -->
        <!-- Templates are not first-class values in XSLT 1.0. -->

        <!-- Obtaining the return value of a function -->
        <!--
            The output of a template is interpolated into the place of the
            call. Often, this is directly into the output of the transform,
            as with most of the above examples. However, it is also possible
            to bind the output as a variable or parameter. This is useful
            for using templates to compute parameters for other templates or
            for XPath functions.
        -->
        <!-- Which is the least of 34, 78, 12, 56? -->
        <xsl:variable name="lesser-demo-result">
            <!-- The variable is bound to the output of this call -->
            <xsl:call-template name="lesser-value">
                <xsl:with-param name="a">
                    <!-- A call as a parameter to another call -->
                    <xsl:call-template name="lesser-value">
                        <xsl:with-param name="a" select="34"/>
                        <xsl:with-param name="b" select="78"/>
                    </xsl:call-template>
                </xsl:with-param>
                <xsl:with-param name="b">
                    <!-- and again -->
                    <xsl:call-template name="lesser-value">
                        <xsl:with-param name="a" select="12"/>
                        <xsl:with-param name="b" select="56"/>
                    </xsl:call-template>
                </xsl:with-param>
            </xsl:call-template>
        </xsl:variable>
        <!-- The variable is used here in an XPath expression -->
        <line>
            <xsl:value-of select="concat('And the answer, which should be 12, is ', $lesser-demo-result, ', of course.')"/>
        </line>

        <!-- Distinguishing built-in functions and user-defined functions -->
        <!-- Virtually all templates are user-defined. -->

    </xsl:template>

    <!-- Templates supporting template demos above -->
    <xsl:template match="/*" mode="nullary-context-demo-mode">
        <xsl:call-template name="nullary-context-demo"/>
    </xsl:template>

    <xsl:template name="nullary-demo">
        <line>No parameters needed here!</line>
    </xsl:template>

    <xsl:template name="nullary-context-demo">
        <!-- When a template is called it has access to the current node of the caller -->
        <xsl:for-each select="self::*">
            <line>The context element here is named "<xsl:value-of select="local-name()"/>"</line>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="ternary-demo">
        <!-- This demo requires, at least semantically, all three parameters. -->
        <xsl:param name="a"/>
        <xsl:param name="b"/>
        <xsl:param name="c"/>
        <line>(<xsl:value-of select="$a"/> * <xsl:value-of select="$b"/>) + <xsl:value-of select="$c"/> = <xsl:value-of select="($a * $b) + $c"/></line>
    </xsl:template>

    <xsl:template name="binary-or-ternary-demo">
        <!-- This demo requires the first two parameters, but defaults the third to 0 if it is not supplied. -->
        <xsl:param name="a"/>
        <xsl:param name="b"/>
        <xsl:param name="c" select="0"/>
        <line>(<xsl:value-of select="$a"/> * <xsl:value-of select="$b"/>) + <xsl:value-of select="$c"/> = <xsl:value-of select="($a * $b) + $c"/></line>
    </xsl:template>

    <xsl:template name="lesser-value">
        <xsl:param name="a"/>
        <xsl:param name="b"/>
        <xsl:choose>
            <xsl:when test="number($a) < number($b)">
                <xsl:value-of select="$a"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$b"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
</xsl:stylesheet>


sub test(a, b, c) :	print a, b, c : end sub

test(1, 2, 3)	// show 1 2 3
test(1, 2)	// show 1 2 0

execute("test", 1, 2, 3)	// show 1 2 3

sub test$(a$)	// show all members of a "list"
	local n, i, t$(1)

	n = token(a$, t$(), ", ")
	for i = 1 to n
		print t$(i), " ";
	next
end sub

test$("1, 2, 3, 4, text, 6, 7, 8, \"include text\"")
print


f(); f(1,2,3,4);
fcn f(a=1){}()  // define and call f, which gets a set to 1
fcn{vm.arglist}(1,2,3,4) // arglist is L(1,2,3,4)
fcn{a1:=vm.nthArg(1)}(1,2,3)  // a1 == 2
(f() == True); (f() and 1 or 2)
if (f()) println()
f(f) // pass f to itself
s:=f()
fcn{}.isType(self.fcn)  //True
fcn{}.len.isType(self.fcn)  //False, len is a Method


module CallingProcs;
	type
		{public} Vector = array {math} * of integer;

	var
		nums: array {math} 4 of integer;
		ints: Vector;
		total: integer;

		procedure Init(): boolean; (* private by default *)
		begin
			nums := [1,2,3,4];
			ints := new Vector(5);
			ints := [2,4,6,8,10];
			return true;
		end Init;

		(* function *)
		procedure Sum(v: Vector): integer;
		var
			i,s: integer;
		begin
			s := 0;
			for i := 0 to len(v) - 1 do
				(* inc is a predefined subroutine *)
				inc(s,v[i])
			end;
			return s
		end Sum;

		(* subroutine
		 * @param v: by value
		 * @param t: by reference
		 *)
		procedure Sum2(v: array {math} * of integer; var t: integer);
		var
			i: integer;
		begin
			t := 0;
			for i := 0 to len(v) - 1 do
				inc(t,v[i])
			end
		end Sum2;
	begin
		Init; (* calling a function without parameters *)
		total := Sum(nums);
		writeln(total);
		(* optional arguments not supported *)
		(* variable arguments through open arrays *)
		writeln(Sum(ints));
		(* named arguments not supported *)
		ints := [1,3,5,7,9];
		Sum2(ints,total);
		writeln(total);
	end CallingProcs.


PackNibbles:
;input: B = top nibble, C = bottom nibble. Outputs to accumulator.
;usage: B = &0X, C = &0Y, => A = &XY
LD A,B
AND %00001111
RLCA
RLCA
RLCA
RLCA
OR C
RET


10 REM functions cannot be called in statement context
20 PRINT FN a(5): REM The function is used in first class context. Arguments are not named
30 PRINT FN b(): REM Here we call a function that has no arguments
40 REM subroutines cannot be passed parameters, however variables are global
50 LET n=1: REM This variable will be visible to the called subroutine
60 GO SUB 1000: REM subroutines are called by line number and do not have names
70 REM subroutines do not return a value, but we can see any variables it defined
80 REM subroutines cannot be used in first class context
90 REM builtin functions are used in first class context, and do not need the FN keyword prefix
100 PRINT SIN(50): REM here we pass a parameter to a builtin function
110 PRINT RND(): REM here we use a builtin function without parameters
120 RANDOMIZE: REM statements are not functions and cannot be used in first class context.


*        CALENDAR FOR REAL PROGRAMMERS     05/03/2017
CALENDAR CSECT
         USING  CALENDAR,R13       BASE REGISTER
         B      72(R15)            SKIP MY SAVEAREA
         DC     17F'0'             MY SAVEAREA
         STM    R14,R12,12(R13)    SAVE CALLER'S REGISTERS
         ST     R13,4(R15)         LINK BACKWARD
         ST     R15,8(R13)         LINK FORWARD
         LR     R13,R15            SET ADDRESSABILITY
         L      R4,YEAR            YEAR
         SRDA   R4,32              .
         D      R4,=F'4'           YEAR//4
         LTR    R4,R4              IF YEAR//4=0
         BNZ    LYNOT
         L      R4,YEAR            YEAR
         SRDA   R4,32              .
         D      R4,=F'100'         YEAR//100
         LTR    R4,R4              IF YEAR//100=0
         BNZ    LY
         L      R4,YEAR            YEAR
         SRDA   R4,32              .
         D      R4,=F'400'         IF YEAR//400
         LTR    R4,R4              IF YEAR//400=0
         BNZ    LYNOT
LY       MVC    ML+2,=H'29'        ML(2)=29  LEAPYEAR
LYNOT    SR     R10,R10            LTD1=0
         LA     R6,1               I=1
LOOPI1   C      R6,=F'31'          DO I=1 TO 31
         BH     ELOOPI1
         XDECO  R6,XDEC            EDIT I
         LA     R14,TD1            TD1
         AR     R14,R10            TD1+LTD1
         MVC    0(3,R14),XDEC+9    SUB(TD1,LTD1+1,3)=PIC(I,3)
         LA     R10,3(R10)         LTD1+3
         LA     R6,1(R6)           I=I+1
         B      LOOPI1
ELOOPI1  LA     R6,1               I=1
LOOPI2   C      R6,=F'12'          DO I=1 TO 12
         BH     ELOOPI2
         ST     R6,M               M=I
         MVC    D,=F'1'            D=1
         MVC    YY,YEAR            YY=YEAR
         L      R4,M               M
         C      R4,=F'3'           IF M<3
         BNL    GE3
         L      R2,M               M
         LA     R2,12(R2)          M+12
         ST     R2,M               M=M+12
         L      R2,YY              YY
         BCTR   R2,0               YY-1
         ST     R2,YY              YY=YY-1
GE3      L      R2,YY              YY
         LR     R1,R2              YY
         SRA    R1,2               YY/4
         AR     R2,R1              YY+(YY/4)
         L      R4,YY              YY
         SRDA   R4,32              .
         D      R4,=F'100'         YY/100
         SR     R2,R5              YY+(YY/4)-(YY/100)
         L      R4,YY              YY
         SRDA   R4,32              .
         D      R4,=F'400'         YY/400
         AR     R2,R5              YY+(YY/4)-(YY/100)+(YY/400)
         A      R2,D               R2=YY+(YY/4)-(YY/100)+(YY/400)+D
         LA     R5,153             153
         M      R4,M               153*M
         LA     R5,8(R5)           153*M+8
         D      R4,=F'5'           (153*M+8)/5
         AR     R5,R2              ((153*M+8)/5+R2
         LA     R4,0               .
         D      R4,=F'7'           R4=MOD(R5,7)  0=SUN 1=MON ... 6=SAT
         LTR    R4,R4              IF J=0
         BNZ    JNE0
         LA     R4,7               J=7
JNE0     BCTR   R4,0               J-1
         MH     R4,=H'3'           J*3
         LR     R10,R4             J1=J*3
         LR     R1,R6              I
         SLA    R1,1               *2
         LH     R11,ML-2(R1)       ML(I)
         MH     R11,=H'3'          J2=ML(I)*3
         MVC    TD2,BLANK          TD2=' '
         LA     R4,TD1             @TD1
         LR     R5,R11             J2
         LA     R2,TD2             @TD2
         AR     R2,R10             @TD2+J1
         LR     R3,R5              J2
         MVCL   R2,R4              SUB(TD2,J1+1,J2)=SUB(TD1,1,J2)
         LR     R1,R6              I
         MH     R1,=H'144'         *144
         LA     R14,DA-144(R1)     @DA(I)
         MVC    0(144,R14),TD2     DA(I)=TD2
         LA     R6,1(R6)           I=I+1
         B      LOOPI2
ELOOPI2  XPRNT  SNOOPY,132         PRINT SNOOPY
         L      R1,YEAR            YEAR
         XDECO  R1,PG+56           EDIT YEAR
         XPRNT  PG,L'PG            PRINT YEAR
         MVC    WDLINE,BLANK       WDLINE=' '
         LA     R10,1              LWDLINE=1
         LA     R8,1               K=1
LOOPK3   C      R8,=F'6'           DO K=1 TO 6
         BH     ELOOPK3
         LA     R4,WDLINE          @WDLINE
         AR     R4,R10             +LWDLINE
         MVC    0(20,R4),WDNA      SUB(WDLINE,LWDLINE+1,20)=WDNA
         LA     R10,20(R10)        LWDLINE=LWDLINE+20
         C      R8,=F'6'           IF K<6
         BNL    ITERK3
         LA     R10,2(R10)         LWDLINE=LWDLINE+2
ITERK3   LA     R8,1(R8)           K=K+1
         B      LOOPK3
ELOOPK3  LA     R6,1               I=1
LOOPI4   C      R6,=F'12'          DO I=1 TO 12 BY 6
         BH     ELOOPI4
         MVC    MOLINE,BLANK       MOLINE=' '
         LA     R10,6              LMOLINE=6
         LR     R8,R6              K=I
LOOPK4   LA     R2,5(R6)           I+5
         CR     R8,R2              DO K=I TO I+5
         BH     ELOOPK4
         LR     R1,R8              K
         MH     R1,=H'10'          *10
         LA     R3,MO-10(R1)       MO(K)
         LA     R4,MOLINE          @MOLINE
         AR     R4,R10             +LMOLINE
         MVC    0(10,R4),0(R3)     SUB(MOLINE,LMOLINE+1,10)=MO(K)
         LA     R10,22(R10)        LMOLINE=LMOLINE+22
         LA     R8,1(R8)           K=K+1
         B      LOOPK4
ELOOPK4  XPRNT  MOLINE,L'MOLINE    PRINT MONTHS
         XPRNT  WDLINE,L'WDLINE    PRINT DAYS OF WEEK
         LA     R7,1               J=1
LOOPJ4   C      R7,=F'106'         DO J=1 TO 106 BY 21
         BH     ELOOPJ4
         MVC    PG,BLANK           CLEAR BUFFER
         LA     R9,PG              PGI=0
         LR     R8,R6              K=I
LOOPK5   LA     R2,5(R6)           I+5
         CR     R8,R2              DO K=I TO I+5
         BH     ELOOPK5
         LR     R1,R8              K
         MH     R1,=H'144'         *144
         LA     R4,DA-144(R1)      DA(K)
         BCTR   R4,0               -1
         AR     R4,R7              +J
         MVC    0(21,R9),0(R4)     SUBSTR(DA(K),J,21)
         LA     R9,22(R9)          PGI=PGI+22
         LA     R8,1(R8)           K=K+1
         B      LOOPK5
ELOOPK5  XPRNT  PG,L'PG            PRINT BUFFER
         LA     R7,21(R7)          J=J+21
         B      LOOPJ4
ELOOPJ4  LA     R6,6(R6)           I=I+6
         B      LOOPI4
ELOOPI4  L      R13,4(0,R13)       RESTORE PREVIOUS SAVEAREA POINTER
         LM     R14,R12,12(R13)    RESTORE CALLER'S REGISTERS
         XR     R15,R15            SET RETURN CODE TO 0
         BR     R14                RETURN TO CALLER
SNOOPY   DC     CL57' ',CL18'INSERT SNOOPY HERE',CL57' '
YEAR     DC     F'1969'            <== 1969
MO       DC     CL10' JANUARY  ',CL10' FEBRUARY ',CL10'  MARCH   '
         DC     CL10'  APRIL   ',CL10'   MAY    ',CL10'   JUNE   '
         DC     CL10'   JULY   ',CL10'  AUGUST  ',CL10'SEPTEMBER '
         DC     CL10' OCTOBER  ',CL10' NOVEMBER ',CL10' DECEMBER '
ML       DC     H'31',H'28',H'31',H'30',H'31',H'30'
         DC     H'31',H'31',H'30',H'31',H'30',H'31'
WDNA     DC     CL20'MO TU WE TH FR SA SU'
M        DS     F
D        DS     F
YY       DS     F
TD1      DS     CL93
TD2      DS     CL144
MOLINE   DS     CL132
WDLINE   DS     CL132
PG       DC     CL132' '           BUFFER FOR THE LINE PRINTER
XDEC     DS     CL12
BLANK    DC     CL144' '
DA       DS     12CL144
         YREGS
         END    CALENDAR


WITH PRINTABLE_CALENDAR;

PROCEDURE REAL_CAL IS

   C: PRINTABLE_CALENDAR.CALENDAR := PRINTABLE_CALENDAR.INIT_132
     ((WEEKDAY_REP =>
          "MO TU WE TH FR SA SO",
       MONTH_REP   =>
         ("      JANUARY       ", "      FEBRUARY      ",
          "       MARCH        ", "       APRIL        ",
          "        MAY         ", "        JUNE        ",
          "        JULY        ", "       AUGUST       ",
          "      SEPTEMBER     ", "       OCTOBER      ",
          "      NOVEMBER      ", "      DECEMBER      ")
      ));

BEGIN
   C.PRINT_LINE_CENTERED("[SNOOPY]");
   C.NEW_LINE;
   C.PRINT(1969, "NINETEEN-SIXTY-NINE");
END REAL_CAL;


'PR' QUOTE 'PR'

'PROC' PRINT CALENDAR = ('INT' YEAR, PAGE WIDTH)'VOID': 'BEGIN'

  ()'STRING' MONTH NAMES = (
      "JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE",
      "JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER"),
    WEEKDAY NAMES = ("SU","MO","TU","WE","TH","FR","SA");
  'FORMAT' WEEKDAY FMT = $G,N('UPB' WEEKDAY NAMES - 'LWB' WEEKDAY NAMES)(" "G)$;

  # 'JUGGLE' THE CALENDAR FORMAT TO FIT THE PRINTER/SCREEN WIDTH #
  'INT' DAY WIDTH = 'UPB' WEEKDAY NAMES(1), DAY GAP=1;
  'INT' MONTH WIDTH = (DAY WIDTH+DAY GAP) * 'UPB' WEEKDAY NAMES-1;
  'INT' MONTH HEADING LINES = 2;
  'INT' MONTH LINES = (31 'OVER' 'UPB' WEEKDAY NAMES+MONTH HEADING LINES+2); # +2 FOR HEAD/TAIL WEEKS #
  'INT' YEAR COLS = (PAGE WIDTH+1) 'OVER' (MONTH WIDTH+1);
  'INT' YEAR ROWS = ('UPB' MONTH NAMES-1)'OVER' YEAR COLS + 1;
  'INT' MONTH GAP = (PAGE WIDTH - YEAR COLS*MONTH WIDTH + 1)'OVER' YEAR COLS;
  'INT' YEAR WIDTH = YEAR COLS*(MONTH WIDTH+MONTH GAP)-MONTH GAP;
  'INT' YEAR LINES = YEAR ROWS*MONTH LINES;

  'MODE' 'MONTHBOX' = (MONTH LINES, MONTH WIDTH)'CHAR';
  'MODE' 'YEARBOX'  = (YEAR  LINES, YEAR  WIDTH)'CHAR';

  'INT' WEEK START = 1; # 'SUNDAY' #

  'PROC' DAYS IN MONTH = ('INT' YEAR, MONTH)'INT':
    'CASE' MONTH 'IN' 31,
      'IF' YEAR 'MOD' 4 'EQ' 0 'AND' YEAR 'MOD' 100 'NE' 0 'OR' YEAR 'MOD' 400 'EQ' 0 'THEN' 29 'ELSE' 28 'FI',
      31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    'ESAC';

  'PROC' DAY OF WEEK = ('INT' YEAR, MONTH, DAY)'INT': 'BEGIN'
    # 'DAY' OF THE WEEK BY 'ZELLER'’S 'CONGRUENCE' ALGORITHM FROM 1887 #
    'INT' Y := YEAR, M := MONTH, D := DAY, C;
    'IF' M <= 2 'THEN' M +:= 12; Y -:= 1 'FI';
    C := Y 'OVER' 100;
    Y 'MODAB' 100;
    (D - 1 + ((M + 1) * 26) 'OVER' 10 + Y + Y 'OVER' 4 + C 'OVER' 4 - 2 * C) 'MOD' 7
  'END';

  'MODE' 'SIMPLEOUT' = 'UNION'('STRING', ()'STRING', 'INT');

  'PROC' CPUTF = ('REF'()'CHAR' OUT, 'FORMAT' FMT, 'SIMPLEOUT' ARGV)'VOID':'BEGIN'
    'FILE' F; 'STRING' S; ASSOCIATE(F,S);
    PUTF(F, (FMT, ARGV));
    OUT(:'UPB' S):=S;
    CLOSE(F)
  'END';

  'PROC' MONTH REPR = ('INT' YEAR, MONTH)'MONTHBOX':'BEGIN'
    'MONTHBOX' MONTH BOX; 'FOR' LINE 'TO' 'UPB' MONTH BOX 'DO' MONTH BOX(LINE,):=" "* 2 'UPB' MONTH BOX 'OD';
    'STRING' MONTH NAME = MONTH NAMES(MONTH);

  # CENTER THE TITLE #
    CPUTF(MONTH BOX(1,(MONTH WIDTH - 'UPB' MONTH NAME ) 'OVER' 2+1:), $G$, MONTH NAME);
    CPUTF(MONTH BOX(2,), WEEKDAY FMT, WEEKDAY NAMES);

    'INT' FIRST DAY := DAY OF WEEK(YEAR, MONTH, 1);
    'FOR' DAY 'TO' DAYS IN MONTH(YEAR, MONTH) 'DO'
      'INT' LINE = (DAY+FIRST DAY-WEEK START) 'OVER' 'UPB' WEEKDAY NAMES + MONTH HEADING LINES + 1;
      'INT' CHAR =((DAY+FIRST DAY-WEEK START) 'MOD' 'UPB' WEEKDAY NAMES)*(DAY WIDTH+DAY GAP) + 1;
      CPUTF(MONTH BOX(LINE,CHAR:CHAR+DAY WIDTH-1),$G(-DAY WIDTH)$, DAY)
    'OD';
    MONTH BOX
  'END';

  'PROC' YEAR REPR = ('INT' YEAR)'YEARBOX':'BEGIN'
    'YEARBOX' YEAR BOX;
    'FOR' LINE 'TO' 'UPB' YEAR BOX 'DO' YEAR BOX(LINE,):=" "* 2 'UPB' YEAR BOX 'OD';
    'FOR' MONTH ROW 'FROM' 0 'TO' YEAR ROWS-1 'DO'
      'FOR' MONTH COL 'FROM' 0 'TO' YEAR COLS-1 'DO'
        'INT' MONTH = MONTH ROW * YEAR COLS + MONTH COL + 1;
        'IF' MONTH > 'UPB' MONTH NAMES 'THEN'
          DONE
        'ELSE'
          'INT' MONTH COL WIDTH = MONTH WIDTH+MONTH GAP;
          YEAR BOX(
            MONTH ROW*MONTH LINES+1 : (MONTH ROW+1)*MONTH LINES,
            MONTH COL*MONTH COL WIDTH+1 : (MONTH COL+1)*MONTH COL WIDTH-MONTH GAP
          ) := MONTH REPR(YEAR, MONTH)
        'FI'
      'OD'
    'OD';
    DONE: YEAR BOX
  'END';

  'INT' CENTER = (YEAR COLS*(MONTH WIDTH+MONTH GAP) - MONTH GAP - 1) 'OVER' 2;
  'INT' INDENT = (PAGE WIDTH - YEAR WIDTH) 'OVER' 2;

  PRINTF((
    $N(INDENT + CENTER - 9)K  G L$, "(INSERT SNOOPY HERE)",
    $N(INDENT + CENTER - 1)K 4D L$, YEAR, $L$,
    $N(INDENT)K N(YEAR WIDTH)(G)  L$, YEAR REPR(YEAR)
  ))
'END';

MAIN: 'BEGIN'
'CO' INSPIRED BY HTTP://WWW.EE.RYERSON.CA/~ELF/hack/realmen.html
           REAL PROGRAMMERS DONT USE PASCAL - ED POST
            DATAMATION, VOLUME 29 NUMBER 7, JULY 1983
              THE REAL PROGRAMMERS NATURAL HABITAT
"TAPED TO THE WALL IS A LINE-PRINTER SNOOPY CALENDER FOR THE YEAR 1969"
'CO'
  'INT' MANKIND STEPPED ON THE MOON = 1969,
      LINE PRINTER WIDTH = 132; # AS AT 1969! #
  PRINT CALENDAR(MANKIND STEPPED ON THE MOON, LINE PRINTER WIDTH)
'END'


CALENDAR(YR){
	LASTDAY := [], DAY := []
	TITLES =
	(LTRIM
	______JANUARY_________________FEBRUARY_________________MARCH_______
	_______APRIL____________________MAY____________________JUNE________
	________JULY___________________AUGUST_________________SEPTEMBER_____
	______OCTOBER_________________NOVEMBER________________DECEMBER______
	)
	STRINGSPLIT, TITLE, TITLES, % CHR(10)
	RES := "________________________________" YR CHR(13) CHR(10)

	LOOP 4 {												; 4 VERTICAL SECTIONS
		DAY[1]:=YR SUBSTR("0" A_INDEX*3 -2, -1) 01
		DAY[2]:=YR SUBSTR("0" A_INDEX*3 -1, -1) 01
		DAY[3]:=YR SUBSTR("0" A_INDEX*3   , -1) 01
		RES .= CHR(13) CHR(10) TITLE%A_INDEX% CHR(13) CHR(10) "SU MO TU WE TH FR SA    SU MO TU WE TH FR SA    SU MO TU WE TH FR SA"
		LOOP , 6 {											; 6 WEEKS MAX PER MONTH
			WEEK := A_INDEX, RES .= CHR(13) CHR(10)
			LOOP, 21 {										; 3 WEEKS TIMES 7 DAYS
				MON := CEIL(A_INDEX/7), THISWD := MOD(A_INDEX-1,7)+1
				FORMATTIME, WD, % DAY[MON], WDAY
				;~ MSGBOX % WD
				FORMATTIME, DD, % DAY[MON], % CHR(100) CHR(100)
				IF (WD>THISWD) {
					RES .= "__ "
					CONTINUE
				}
				DD := ((WEEK>3) && DD <10) ? "__" : DD, RES .= DD " ", LASTDAY[MON] := DAY[MON], DAY[MON] +=1, D
				RES .= ((WD=7) && A_INDEX < 21) ? "___" : ""
				FORMATTIME, DD, % DAY[MON], % CHR(100) CHR(100)
			}
		}
		RES .= CHR(13) CHR(10)
	}
	STRINGREPLACE, RES, RES,_,%A_SPACE%, ALL
	STRINGREPLACE, RES, RES,%A_SPACE%0,%A_SPACE%%A_SPACE%, ALL
	RETURN RES
}


DECLARE MON$[] = { "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER" }
DECLARE MON[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
Y$ = "1969"
' Leap year
INCR MON[1], IIF(MOD(VAL(Y$), 4) = 0 OR MOD(VAL(Y$), 100) = 0 AND MOD(VAL(Y$), 400) <> 0, 1, 0)
PRINT ALIGN$("[SNOOPY HERE]", 132, 2)
PRINT ALIGN$(Y$, 132, 2)
FOR NR = 0 TO 11
    ROW = 3
    GOTOXY 1+(NR %6)*22, ROW+(NR/6)*9
    PRINT ALIGN$(MON$[NR], 21, 2);
    INCR ROW
    GOTOXY 1+(NR %6)*22, ROW+(NR/6)*9
    PRINT ALIGN$("MO TU WE TH FR SA SU", 21, 2);
    INCR ROW
    ' Each day
    FOR D = 1 TO MON[NR]
        ' Zeller
        J = VAL(LEFT$(Y$, 2))
        K = VAL(MID$(Y$, 3, 2))
        M = NR+1
        IF NR < 2 THEN
            INCR M, 12
            DECR K
        END IF
        H = (D + ((M+1)*26)/10 + K + (K/4) + (J/4) + 5*J)
        DAYNR = MOD(H, 7) - 2
        IF DAYNR < 0 THEN INCR DAYNR, 7
        IF DAYNR = 0 AND D > 1 THEN INCR ROW
        GOTOXY 1+(NR %6)*22+DAYNR*3, ROW+(NR/6)*9
        PRINT D;
    NEXT
NEXT


      VDU 23,22,1056;336;8,16,16,128

      YEAR = 1969
      PRINT TAB(62) "[SNOOPY]" TAB(64); YEAR
      DIM DOM(5), MJD(5), DM(5), MONTH$(11)
      DAYS$ = "SU MO TU WE TH FR SA"
      MONTH$() = "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE", \
      \ "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"

      FOR MONTH = 1 TO 7 STEP 6
        PRINT
        FOR COL = 0 TO 5
          MJD(COL) = FNMJD(1, MONTH + COL, YEAR)
          MONTH$ = MONTH$(MONTH + COL - 1)
          PRINT TAB(COL*22 + 11 - LEN(MONTH$)/2) MONTH$;
        NEXT
        FOR COL = 0 TO 5
          PRINT TAB(COL*22 + 1) DAYS$;
          DM(COL) = FNDIM(MONTH + COL, YEAR)
        NEXT
        DOM() = 1
        COL = 0
        REPEAT
          DOW = FNDOW(MJD(COL))
          IF DOM(COL)<=DM(COL) THEN
            PRINT TAB(COL*22 + DOW*3 + 1); DOM(COL);
            DOM(COL) += 1
            MJD(COL) += 1
          ENDIF
          IF DOW=6 OR DOM(COL)>DM(COL) COL = (COL + 1) MOD 6
        UNTIL DOM(0)>DM(0) AND DOM(1)>DM(1) AND DOM(2)>DM(2) AND \
        \     DOM(3)>DM(3) AND DOM(4)>DM(4) AND DOM(5)>DM(5)
        PRINT
      NEXT
      END

      DEF FNMJD(D%,M%,Y%) : M% -= 3 : IF M% < 0 M% += 12 : Y% -= 1
      = D% + (153*M%+2)DIV5 + Y%*365 + Y%DIV4 - Y%DIV100 + Y%DIV400 - 678882

      DEF FNDOW(J%) = (J%+2400002) MOD 7

      DEF FNDIM(M%,Y%)
      CASE M% OF
        WHEN 2: = 28 + (Y%MOD4=0) - (Y%MOD100=0) + (Y%MOD400=0)
        WHEN 4,6,9,11: = 30
        OTHERWISE = 31
      ENDCASE


tcc -DSTRUCT=struct -DCONST=const -DINT=int -DCHAR=char -DVOID=void -DMAIN=main -DIF=if -DELSE=else -DWHILE=while -DFOR=for -DDO=do -DBREAK=break -DRETURN=return -DPUTCHAR=putchar UCCALENDAR.c