diff --git a/v2.v b/v2.v index 6f3906cb03..d62d6099ad 100644 --- a/v2.v +++ b/v2.v @@ -3,7 +3,7 @@ module main import ( v.parser v.table - v.cgen + v.gen os ) @@ -11,6 +11,7 @@ const ( cdefs = ' #define true 1 #define false 0 +typedef int bool; typedef struct { char* str; } string; typedef double f64; string tos3(char* s) { return (string){ .str = s }; } @@ -22,7 +23,7 @@ fn main() { text := os.read_file(path)? table := &table.Table{} program := parser.parse_file(text, table) - res := cgen.gen(program) + res := gen.cgen(program) mut out := os.create('out.c')? out.writeln(cdefs) out.writeln(res) diff --git a/vlib/v/cgen/cgen.v b/vlib/v/gen/cgen.v similarity index 98% rename from vlib/v/cgen/cgen.v rename to vlib/v/gen/cgen.v index 196d0bbbb8..f646555b46 100644 --- a/vlib/v/cgen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -1,4 +1,4 @@ -module cgen +module gen import ( strings @@ -10,7 +10,7 @@ struct Gen { out strings.Builder } -pub fn gen(program ast.Program) string { +pub fn cgen(program ast.Program) string { mut g := Gen{ out: strings.new_builder(100) } diff --git a/vlib/v/cgen/cgen_test.v b/vlib/v/gen/cgen_test.v similarity index 84% rename from vlib/v/cgen/cgen_test.v rename to vlib/v/gen/cgen_test.v index befc34696c..f008c38b21 100644 --- a/vlib/v/cgen/cgen_test.v +++ b/vlib/v/gen/cgen_test.v @@ -3,7 +3,7 @@ import ( filepath v.parser v.ast - v.cgen + v.gen v.table term ) @@ -17,15 +17,15 @@ fn test_c_files() { vexe := os.getenv('VEXE') vroot := filepath.dir(vexe) for i in 1 .. nr_tests + 1 { - text := os.read_file('$vroot/vlib/v/cgen/tests/${i}.v') or { + text := os.read_file('$vroot/vlib/v/gen/tests/${i}.v') or { panic(err) } - ctext := os.read_file('$vroot/vlib/v/cgen/tests/${i}.c') or { + ctext := os.read_file('$vroot/vlib/v/gen/tests/${i}.c') or { panic(err) } table := &table.Table{} program := parser.parse_file(text, table) - res := cgen.gen(program) + res := gen.cgen(program) if compare_texts(res, ctext) { eprintln('${i}... ' + term.green('OK')) } diff --git a/vlib/v/gen/jsgen.v b/vlib/v/gen/jsgen.v new file mode 100644 index 0000000000..a59289e420 --- /dev/null +++ b/vlib/v/gen/jsgen.v @@ -0,0 +1,160 @@ +module gen + +import ( + strings + v.ast + term +) + +struct JsGen { + out strings.Builder +} + +pub fn jsgen(program ast.Program) string { + mut g := JsGen{ + out: strings.new_builder(100) + } + for stmt in program.stmts { + g.stmt(stmt) + g.writeln('') + } + return (g.out.str()) +} + +pub fn (g &JsGen) save() {} + +pub fn (g mut JsGen) write(s string) { + g.out.write(s) +} + +pub fn (g mut JsGen) writeln(s string) { + g.out.writeln(s) +} + +fn (g mut JsGen) stmt(node ast.Stmt) { + match node { + ast.AssignStmt { + g.expr(it.left) + g.write(' $it.op.str() ') + g.expr(it.right) + g.writeln(';') + } + ast.FnDecl { + g.write('/** @return { $it.typ.name } **/\nfunction ${it.name}(') + for arg in it.args { + g.write(' /** @type { arg.typ.name } **/ $arg.name') + } + g.writeln(') { ') + for stmt in it.stmts { + g.stmt(stmt) + } + g.writeln('}') + } + ast.Return { + g.write('return ') + g.expr(it.expr) + g.writeln(';') + } + ast.VarDecl { + g.write('var /* $it.typ.name */ $it.name = ') + g.expr(it.expr) + g.writeln(';') + } + ast.ForStmt { + g.write('while (') + g.expr(it.cond) + g.writeln(') {') + for stmt in it.stmts { + g.stmt(stmt) + } + g.writeln('}') + } + ast.StructDecl { + // g.writeln('typedef struct {') + // for field in it.fields { + // g.writeln('\t$field.typ.name $field.name;') + // } + g.writeln('var $it.name = function() {};') + } + ast.ExprStmt { + g.expr(it.expr) + match it.expr { + // no ; after an if expression + ast.IfExpr {} + else { + g.writeln(';') + } + } + } + else { + verror('jsgen.stmt(): bad node') + } + } +} + +fn (g mut JsGen) expr(node ast.Expr) { + // println('cgen expr()') + match node { + ast.IntegerLiteral { + g.write(it.val.str()) + } + ast.FloatLiteral { + g.write(it.val) + } + ast.UnaryExpr { + g.expr(it.left) + g.write(' $it.op ') + } + ast.StringLiteral { + g.write('tos3("$it.val")') + } + ast.BinaryExpr { + g.expr(it.left) + g.write(' $it.op.str() ') + g.expr(it.right) + } + // `user := User{name: 'Bob'}` + ast.StructInit { + g.writeln('/*$it.typ.name*/{') + for i, field in it.fields { + g.write('\t$field : ') + g.expr(it.exprs[i]) + g.writeln(', ') + } + g.write('}') + } + ast.CallExpr { + g.write('${it.name}(') + for i, expr in it.args { + g.expr(expr) + if i != it.args.len - 1 { + g.write(', ') + } + } + g.write(')') + } + ast.Ident { + g.write('$it.name') + } + ast.BoolLiteral { + if it.val == true { + g.write('true') + } + else { + g.write('false') + } + } + ast.IfExpr { + g.write('if (') + g.expr(it.cond) + g.writeln(') {') + for stmt in it.stmts { + g.stmt(stmt) + } + g.writeln('}') + } + else { + println(term.red('jsgen.expr(): bad node')) + } + } +} diff --git a/vlib/v/cgen/tests/1.c b/vlib/v/gen/tests/1.c similarity index 100% rename from vlib/v/cgen/tests/1.c rename to vlib/v/gen/tests/1.c diff --git a/vlib/v/cgen/tests/1.v b/vlib/v/gen/tests/1.v similarity index 100% rename from vlib/v/cgen/tests/1.v rename to vlib/v/gen/tests/1.v diff --git a/vlib/v/cgen/tests/2.c b/vlib/v/gen/tests/2.c similarity index 100% rename from vlib/v/cgen/tests/2.c rename to vlib/v/gen/tests/2.c diff --git a/vlib/v/cgen/tests/2.v b/vlib/v/gen/tests/2.v similarity index 100% rename from vlib/v/cgen/tests/2.v rename to vlib/v/gen/tests/2.v diff --git a/vlib/v/parser/parser_test.v b/vlib/v/parser/parser_test.v index 76d65928b3..a11f67ee22 100644 --- a/vlib/v/parser/parser_test.v +++ b/vlib/v/parser/parser_test.v @@ -2,7 +2,7 @@ module parser import ( v.ast - v.cgen + v.gen v.table ) @@ -23,7 +23,7 @@ x := 10 ' table := &table.Table{} prog := parse_file(s, table) - res := cgen.gen(prog) + res := gen.cgen(prog) println(res) } @@ -79,7 +79,7 @@ fn test_parse_expr() { program := ast.Program{ stmts: e } - res := cgen.gen(program) + res := gen.cgen(program) println('========') println(res) println('========')