6.8 KiB
fLisp
- S-expressions:
(<function> [arg0 ... argN])
Will call function with optional args arg0-argN
([*]<variable> [arg | *arg] [arg2])
If arg is given, it will assign arg to variable, then return variable
If assigning to a vector or string :- if variable is a string, arg may be a string literal. In this case,
variable becomes the string literal with or without*
specified - In the same way, if variable is a vector, arg may be a vector literal, and the same rules apply
- If
*
is specified before variable, arg will replace the vector - Otherwise, if only arg is given, it will return the element at position
arg of variable. If arg2 is given, it will set the element at position arg of variable to arg2.
Examples:
For vectors and strings, it's a shallow copy (data is the same) unless afLisp : (let:vec:int a 5) C : int a[5]; fLisp : (a 0 69) C : a[0] = 69; fLisp : (let:int x) (x (a 0)) C : int x = a[0]; fLisp : (let:str hello) (hello "Hello !") (*hello "Hello !") # equivalent C : char *hello = "Hello !";
*
is specified before[arg]
- if variable is a string, arg may be a string literal. In this case,
- Literals:
Literals are of the following form:1234
: int literal12.34
: float literal"abcd"
: string literal(1,2,3,4)
: vector literal. All values must be of the same type Null and fix literals do not exist. "Fix" type constants may exist by assigning to a fix typed variable, such as(let:fix x 0.5)
, where x will be of value 0.5 in fixed point
- Comments are indicated by
#
. The whole rest of the line is ignored by the
parser - Compiled to bytecode
In this document :
<...>
:
Mandatory argument[...]
:
Optional argument|
:
Or
Core types
null
:
Represents a null value - always evaluates to falseint
:
32 bit signed integer, evaluates to false if zero and true otherwisefix
:
16:16 bit fixed point signed integer, same evaluation rules as intsfloat
:
32bit IEEE floating point value, same evaluation as ints (within
FL_ESPILOǸ̀
)str
:
ASCII character string - always evaluates to falsefn
:
Function, function "variables" are inherently of type fn - handle with care !vec
:
Vectors of any type
Core functions
-
(var[:type] <name> [size])
:
Declares a global variable of optional type type and name name
if type is of format:vec:<type>
, the variable will be a vector of type type, and optional size size (otherwise size 0)
(if type isn't specified it is inferred) -
(let[:type] <name>)
:
Same as var, but variable is of local scope (recommended) -
(if <cond> [expressions])
:
If cond evaluates to true, will execute optional expressions -
(else [expressions])
:
Must follow a if, will execute if the if's cond evaluates to false -
(while <cond> [expressions])
:
while cond evalutates to true, will execute optional expressions -
(for (<vec> <var>) [expressions])
Will initialize a local scope variable var with the type of the vector vec,
and execute expressions for every element of vec. var will be set to the
element of vec interated on Example:(let:vec:int a (1,2,3)) (for (a i) (write i) (write " ") )
will display
1 2 3
-
(fn (<name> [arg0[:type] ... argN[:type]]) [expressions])
:
Declares a function of name name, optional args arg0-argN with optional
types (recommended to explicit them), that executes optional expressions
The function will return the value of the last expression
Passed vectors and strings are shallow copied
The name cannot be a variable -
(import <lib0> [... libN])
:
Import the functions and variables from lib0-libN
For the following numerical functions, values must be scalars (except + and =,
where they may be strings), and of the same type
-
(+ <a> <b>)
:
Returns a+b, if they are both strings they will be concatenated -
(- <a> <b>)
:
Returns a-b -
(* <a> <b>)
:
Returns a×b -
(/ <a> <b>)
:
Returns a/b -
(% <a> <b>)
:
Returns a%b -
(< <a> <b>)
:
Returns 1 if a < b, else 0 -
̀
(<= <a> <b>)
:
Returns 1 if a <= b, else 0 -
(= <a> <b>)̀̀
:
Returns 1 if a == b, else 0 -
(>= <a> <b>)
:
Returns 1 if a >= b, else 0 -
(> <a> <b>)
:
Returns 1 if a > b, else 0 -
(! <a>)
:
If a evaluates to false, returns true, and false otherwise -
(and <a> <b>)
:
Logical and on a and b -
(or <a> <b>)
: Logical or on a and b -
(is<:type> <arg>)
:
Returns 1 if arg is of type type -
(<:type> <arg>)
:
Will attempt to convert arg to type, returns it on success, and returns null on failure. -
(len <vec>)
: Returns the length of vector vec. -
(push <vec> <arg>)
: Adds item arg to the end of vec, increasing the size of vec -
(pop <vec> <arg>)
: Deletes item at pos arg from vec, and returns it
console functions ((import console)
)
(input)
:
Will try to get input from the user, returns it as a string(write <var>)
:
Will try to convert var to a string then print it to the console(newline)
:
Will print a newline to the console (newline characters aren't escaped with
write)
gint functions
TODO
Bytecode
- 8 byte Value :
2 bytes tag, 6 bytes value itself - 4 byte bytecode ops:
1 byte op, 3 byte args (named 1-3)
Bytecode types
T_Null̀̀
-> nullT_Int
-> intT_Fix
-> fixT_Float
-> floatT_Str
-> string :- If shorter than 4 chars (+
\0
), is a "compact string" - Otherwise, gets converted to a vector, inherently of chars
- If shorter than 4 chars (+
T_Fn
-> fn / function
Bytecode operations :
if just 1, 2 or 3, means the value at pos 1,2,3 of the stack if #1,#2,#3, the immediate value of 1,2,3 if 1:2 / 1:2:3, means stitching 1,2,3 together as a 2 or 3 byte value
add
: 1+2 -> stacksub
: 1-2 -> stackmul
: 1×2 -> stackdiv
: 1/2 -> stackmod
: 1%2 -> stackcall
: calls 1ret
: returns to callermov
: 1 -> 2copy
: deepcopy of 1 -> 2get
: value at pos 2 of vector 1 -> stackset
: set value at pos 2 of vector 1 to 3gt
: 1>2 -> stackge
: 1>=2 -> stackeq
: 1==2 -> stackjmp
: Jumps to bytecode at relative 2:3brt
: Jumps to bytecode at relative 2:3 if 1cast
: Casts 1 to the type of 2 -> 1fcast
: Casts 1 to the type of 2:3 -> 1init
: value of type 2:3 and size 1 -> stackfcall
: calls function of hash 1:2:3pop
: pop value 1popl
: pops the last #2 values on stack, starting from #1cst0
: 2:3 -> LSW of 3cst1
: 2:3 -> MSW of 3iter
: Iterates on vector 1, keeping track with int value at 2, and sets
int value at 3 to 1 when done
to 1not
: !1 -> stackand
: 1 && 2 -> stackor
: 1 || 2 -> stack