Twocode is a language designed for code generation. To compile Twocode, start an interpreter and load the program. You can edit the code in all possible ways, then transpile it to a simple Java-like program.
Here we explore the Code type and what one can do with it in the interpreter.
In [1]:
func f(a, b):
return 5
f(1, 2)
Out[1]:
In [2]:
f
Out[2]:
The function's body is stored in its code attribute. The body is an AST (Abstract Syntax Tree), a parsed Code object.
We can view a Code object as source code, or as the raw syntax tree.
In [3]:
f.code
Out[3]:
In [4]:
f.code.tree()
Out[4]:
In [5]:
f.code = macro return (a + b)
print(
f.source(),
f(1, 2),
sep="\n")
Now the function works as if this was its body in the first place. The a and b identifiers are evaluated in its scope. return 1 + 2 returns 3.
In [6]:
var args = f.args
args
Out[6]:
In [7]:
class C:
var x:Int = 10
func msg(s:String):
print("in C.msg", s)
var fields = C.__fields__
fields
Out[7]:
A class's __fields__ is a map from field names to Attr and Func objects.
The method has a hidden this:C prepended to its arguments.
In [8]:
C.msg
Out[8]:
In [9]:
args = [Arg(name="this", type=C)] + args
f.args = args
f.code = (this -> (x * a + b)).code
fields["f"] = f
C.__fields__ = fields
C
Out[9]:
This is the new "source code" of C.
In [10]:
var c = C()
c.f(2, 3)
Out[10]: