Skip to main content

module lang::flybytes::demo::protol::Compiler

rascal-0.40.17
flybytes-0.2.8

Usage

import lang::flybytes::demo::protol::Compiler;

Source code

http://github.com/usethesource/flybytes/blob/main/src/lang/flybytes/demo/protol/Compiler.rsc

Dependencies

import lang::flybytes::Syntax;
import lang::flybytes::Compiler;
import lang::flybytes::demo::protol::Syntax;
import lang::flybytes::api::Object;
import lang::flybytes::api::System;
import ParseTree;
import String;

function testProtol

void testProtol() {
tree = parse(#start[Program], |project://flybytes/src/lang/flybytes/demo/protol/fact.protol|).top;
compileProgram(tree, "ProtolFactorial", |project://flybytes/generated|);

tree = parse(#start[Program], |project://flybytes/src/lang/flybytes/demo/protol/inheritance.protol|).top;
compileProgram(tree, "ProtolInheritance", |project://flybytes/generated|);

tree = parse(#start[Program], |project://flybytes/src/lang/flybytes/demo/protol/missing.protol|).top;
compileProgram(tree, "ProtolMissing", |project://flybytes/generated|);

tree = parse(#start[Program], |project://flybytes/src/lang/flybytes/demo/protol/fields.protol|).top;
compileProgram(tree, "ProtolFields", |project://flybytes/generated|);
}

function protoClass

str protoClass() {
res = "Proto_<program>_<prototypes>";
prototypes += 1;
return res;
}

function compileProgram

void compileProgram(Program p, str name, loc binFolder) {
prototypes = 0;
program = name;

classes = compile(p, name);
for (cl <- classes) {
compileClass(cl, binFolder + "<cl.\type.name>.class", version=v1_8(), debugMode=true);
}
}

function getInt

Exp getInt(Exp rec) = invokeDynamic(bootstrap(Prototype, "bootstrap", []), Prototype_getInteger, [rec]);

function getArray

Exp getArray(Exp rec) = invokeDynamic(bootstrap(Prototype, "bootstrap", []), Prototype_getArray, [rec]);

data Type

data Type  
= prototype(str name, list[Method] methods, list[Field] fields)
;

function compile

list[Class] compile(Program p, str name) { 
progClass = class(object(name),
methods=[
main("args", [*compileAll(p.commands), \return()])[src=p@\loc]
]
)[src=p@\loc];

allClasses = [removePrototypeClasses(progClass), *extractPrototypeClasses(progClass)];

return declareVariables(allClasses);
}

function compileAll

list[Stat] compileAll(Command* commands) = [compile(c)[src=c@\loc] | c <- commands];

function compile

Stat compile((Command) `<Id id> = <Expr v>;`)
= store("<id>", compile(v));

Stat compile((Command) `<Expr obj>.<Id name> = <Expr v>;`)
= \do(invokeDynamic(bootstrap(Prototype, "bootstrap", []), methodDesc(Prototype, "$set_<name>", [Prototype]), [compile(obj), compile(v)]));

function PROTO

Exp PROTO() = getStatic(Prototype, Prototype, "PROTO");

function compile

Stat compile((Command) `<Expr array>[<Expr index>] = <Expr v>;`)
= astore(compile(array), getInt(compile(index)), compile(v));

Stat compile((Command) `if(<Expr cond >) { <Command* thenPart> } else { <Command* elsePart> }`)
= \if(compile(cond), compileAll(thenPart), compileAll(elsePart));

Stat compile((Command) `while(<Expr cond>) { <Command* body> }`)
= \while(compile(cond), compileAll(body));

Stat compile((Command) `<Expr e>;`) = \do(compile(e));

Stat compile((Command) `return <Expr e>;`) = \return(compile(e));

Stat compile((Command) `print <Expr e>;`) = stdout(compile(e));

Exp compile(e:(Expr) `this`) = load("this", src=e@\loc);

Exp compile((Expr) `<Expr rec>.<Id name>(<{Expr ","}* args>)`)
= invokeDynamic(bootstrap(Prototype, "bootstrap", []), methodDesc(Prototype, "<name>", [Prototype]/*receiver*/ + [Prototype | _ <- args] ), [compile(rec), *compileList(args) ])[src=name@\loc];

function compileList

list[Exp] compileList({Expr ","}* args) = [compile(a)[src=a@\loc] | a <- args];

function compile

Exp compile(x:(Expr) `[<{Expr ","}* elems>]`)
= new(Arr, [array(Prototype)], [newInitArray(array(Prototype), [compile(e) | e <- elems])])[src=x@\loc];

Exp compile((Expr) `<Expr receiver>.<Id name>`)
= invokeDynamic(bootstrap(Prototype, "bootstrap", []), methodDesc(Prototype, "$get_<name>", []), [compile(receiver)])[src=name@\loc];

Exp compile(x:(Expr) `new`) = new(Prototype, [Prototype], [PROTO()])[src=x@\loc];

Exp compile(x:(Expr) `new <Expr p>`) = new(Prototype, [Prototype], [compile(p)])[src=x@\loc];

Exp compile(x:(Expr) `new { <Definition* defs> }`)
= new(prototype(protoClass(), methods(defs), fields(defs)), [Prototype], [PROTO()])[src=x@\loc];

Exp compile(x:(Expr) `new <Expr p> { <Definition* defs> }`)
= new(prototype(protoClass(), methods(defs), fields(defs)), [Prototype], [compile(p)])[src=x@\loc];

Exp compile((Expr) `(<Expr e>)`) = compile(e);

Exp compile(x:(Expr) `<Id i>`) = load("<i>", src=x@\loc);

Exp compile(x:(Expr) `<Int i>`) = newInt(iconst(toInt("<i>")))[src=x@\loc];

Exp compile(x:(Expr) `<String s>`) = new(Str, [string()], [sconst("<s>"[1..-1])])[src=x@\loc];

Exp compile(x:(Expr) `<Expr a>[<Expr index>]`)
= aload(getArray(compile(a)), getInt(compile(index)))[src=x@\loc];

function newInt

Exp newInt(Exp e) = new(Int, [integer()], [e]);

function compile

Exp compile(Expr l, Expr r, Exp (Exp, Exp) op) 
= op(getInt(compile(l)), getInt(compile(r)));

Exp compile(x:(Expr) `<Expr l> * <Expr r>`)
= newInt(compile(l, r, mul)[src=x@\loc]);

Exp compile(x:(Expr) `<Expr l> / <Expr r>`)
= newInt(compile(l, r, div)[src=x@\loc]);

Exp compile(x:(Expr) `<Expr l> + <Expr r>`)
= newInt(compile(l, r, add)[src=x@\loc]);

Exp compile(x:(Expr) `<Expr l> - <Expr r>`)
= newInt(compile(l, r, sub)[src=x@\loc]);

Exp compile(x:(Expr) `<Expr l> == <Expr r>`)
= equals(compile(l), compile(r)[src=x@\loc]);

Exp compile(x:(Expr) `<Expr l> != <Expr r>`)
= neg(equals(compile(l), compile(r))[src=x@\loc]);

Exp compile(x:(Expr) `<Expr l> \<\< <Expr r>`)
= invokeVirtual(Prototype, compile(l), methodDesc(Prototype, "concat", [Prototype]), [compile(r)])[src=x@\loc];

Exp compile(x:(Expr) `<Expr l> \<= <Expr r>`)
= compile(l, r, le)[src=x@\loc];

Exp compile(x:(Expr) `<Expr l> \< <Expr r>`)
= compile(l, r, lt)[src=x@\loc];

Exp compile(x:(Expr) `<Expr l> \> <Expr r>`)
= compile(l, r, gt)[src=x@\loc];

Exp compile(x:(Expr) `<Expr l> \>= <Expr r>`)
= compile(l, r, ge)[src=x@\loc];

function methods

list[Method] methods(Definition* defs) 
= [ method("<name>", args, commands)[src=name@\loc]
| (Definition) `<Id name>(<{Id ","}* args>) { <Command* commands> }` <- defs]
+
[ method("missing", missingArgs(name, args), commands)[src=d@\loc]
| d:(Definition) `missing(<Id name>, <Id args>) { <Command* commands> }` <- defs]
+
[ getter("<name>")[src=name@\loc], setter("<name>")[src=name@\loc] | (Definition) `<Id name> = <Expr _>` <- defs]
;

function getter

Method getter(str name) 
= method(\public(), Prototype, "$get_<name>", [], [\return(getField(Prototype, "<name>"))]);

function setter

Method setter(str name)
= method(\public(), \void(), "$set_<name>", [var(Prototype, "a")], [putField(Prototype, "<name>", load("a")), \return()]);

function missingArgs

{Id ","}* missingArgs(Id name, Id args)
= ((Definition) `dummy(<Id name>, <Id args>) { }`).args;

function fields

list[Field] fields(Definition* defs)  
= [ field("<name>", val)[src=name@\loc] | (Definition) `<Id name> = <Expr val>` <- defs];

function method

Method method(str name, {Id ","}* args, Command* commands)
= method(\public(), Prototype, name, [var(Prototype, "<a>") | a <- args], compileAll(commands));

function field

Field field(str name, Expr val)
= field(Prototype, name, init=compile(val), modifiers={\public()});

function declareVariables

&T declareVariables(&T classes) 
= visit(classes) {
case method(Signature desc, list[Formal] formals, list[Stat] block, modifiers=m) =>
method(desc, formals, [*ds, *block], modifiers=m)
when
// transform assignments to declarations and remove duplicates:
set[Stat] ds := { decl(Prototype, name) | /store(str name, _) := block}
};

function removePrototypeClasses

Class removePrototypeClasses(Class main) = visit(main) {
case prototype(n, _, _) => object(n)
};

function extractPrototypeClasses

list[Class] extractPrototypeClasses(Class main) 
= [ class(object(name),
super=Prototype,
methods=[*ms,
// public Class(Prototype proto) { super(proto); }
constructor(\public(), [var(Prototype, "proto")], [
invokeSuper([Prototype], [load("proto")]),
\return()
])
],
fields=fs
)[src=main.src]
| /prototype(str name, ms, fs) := main];