diff --git a/vlib/v/builder/builder.v b/vlib/v/builder/builder.v index 79598dd0e9..81e0116054 100644 --- a/vlib/v/builder/builder.v +++ b/vlib/v/builder/builder.v @@ -7,6 +7,7 @@ import v.util import v.ast import v.vmod import v.checker +import v.transformer import v.parser import v.markused import v.depgraph @@ -20,6 +21,7 @@ pub: mut: pref &pref.Preferences checker &checker.Checker + transformer &transformer.Transformer out_name_c string out_name_js string max_nr_errors int = 100 @@ -60,6 +62,7 @@ pub fn new_builder(pref &pref.Preferences) Builder { pref: pref table: table checker: checker.new_checker(table, pref) + transformer: transformer.new_transformer(pref) compiled_dir: compiled_dir max_nr_errors: if pref.error_limit > 0 { pref.error_limit } else { 100 } cached_msvc: msvc @@ -86,6 +89,9 @@ pub fn (mut b Builder) middle_stages() ? { b.checker.check_files(b.parsed_files) util.timing_measure('CHECK') b.print_warnings_and_errors() + util.timing_start('TRANSFORM') + b.transformer.transform_files(b.parsed_files) + util.timing_measure('TRANSFORM') // b.table.complete_interface_check() if b.pref.skip_unused { diff --git a/vlib/v/gen/c/testdata/addition.c.must_have b/vlib/v/gen/c/testdata/addition.c.must_have new file mode 100644 index 0000000000..300bd6a9f2 --- /dev/null +++ b/vlib/v/gen/c/testdata/addition.c.must_have @@ -0,0 +1 @@ +int zzz = 579 \ No newline at end of file diff --git a/vlib/v/gen/c/testdata/addition.out b/vlib/v/gen/c/testdata/addition.out new file mode 100644 index 0000000000..72b67e0ede --- /dev/null +++ b/vlib/v/gen/c/testdata/addition.out @@ -0,0 +1 @@ +579 \ No newline at end of file diff --git a/vlib/v/gen/c/testdata/addition.vv b/vlib/v/gen/c/testdata/addition.vv new file mode 100644 index 0000000000..ff95896a4e --- /dev/null +++ b/vlib/v/gen/c/testdata/addition.vv @@ -0,0 +1,4 @@ +fn main() { + zzz := 123 + 456 + println(zzz) +} \ No newline at end of file diff --git a/vlib/v/transformer/transformer.v b/vlib/v/transformer/transformer.v new file mode 100644 index 0000000000..61a2d915ee --- /dev/null +++ b/vlib/v/transformer/transformer.v @@ -0,0 +1,220 @@ +module transformer + +import v.pref +import v.ast + +pub struct Transformer { + pref &pref.Preferences +} + +pub fn new_transformer(pref &pref.Preferences) &Transformer { + return &Transformer{ + pref: pref + } +} + +pub fn (t Transformer) transform_files(ast_files []&ast.File) { + for i in 0 .. ast_files.len { + file := unsafe { ast_files[i] } + t.transform(file) + } +} + +pub fn (t Transformer) transform(ast_file &ast.File) { + for mut stmt in ast_file.stmts { + t.stmt(mut stmt) + } +} + +fn (t Transformer) stmt(mut node ast.Stmt) { + match mut node { + ast.EmptyStmt {} + ast.NodeError {} + ast.AsmStmt {} + ast.AssertStmt {} + ast.AssignStmt { + for mut right in node.right { + right = t.expr(right) + } + } + ast.Block { + for mut stmt in node.stmts { + t.stmt(mut stmt) + } + } + ast.BranchStmt {} + ast.CompFor {} + ast.ConstDecl { + for mut field in node.fields { + expr := t.expr(field.expr) + field = ast.ConstField{ + ...(*field) + expr: expr + } + } + } + ast.DeferStmt {} + ast.EnumDecl {} + ast.ExprStmt { + expr := t.expr(node.expr) + node = &ast.ExprStmt{ + ...node + expr: expr + } + } + ast.FnDecl { + for mut stmt in node.stmts { + t.stmt(mut stmt) + } + } + ast.ForCStmt {} + ast.ForInStmt {} + ast.ForStmt {} + ast.GlobalDecl {} + ast.GotoLabel {} + ast.GotoStmt {} + ast.HashStmt {} + ast.Import {} + ast.InterfaceDecl {} + ast.Module {} + ast.Return { + for mut expr in node.exprs { + expr = t.expr(expr) + } + } + ast.SqlStmt {} + ast.StructDecl {} + ast.TypeDecl {} + } +} + +fn (t Transformer) expr(node ast.Expr) ast.Expr { + match node { + ast.InfixExpr { return t.infix_expr(node) } + else { return node } + } +} + +fn (t Transformer) infix_expr(original ast.InfixExpr) ast.Expr { + mut node := original + node.left = t.expr(node.left) + node.right = t.expr(node.right) + mut pos := node.left.position() + pos.extend(node.pos) + pos.extend(node.right.position()) + left_node := node.left + right_node := node.right + match left_node { + ast.BoolLiteral { + match right_node { + ast.BoolLiteral { + match node.op { + .and { + return ast.BoolLiteral{ + val: left_node.val && right_node.val + } + } + .logical_or { + return ast.BoolLiteral{ + val: left_node.val || right_node.val + } + } + else { + return node + } + } + } + else { + return node + } + } + } + ast.StringLiteral { + match right_node { + ast.StringLiteral { + match node.op { + .plus { + return ast.StringLiteral{ + val: left_node.val + right_node.val + pos: pos + } + } + else { + return node + } + } + } + else { + return node + } + } + } + ast.IntegerLiteral { + match right_node { + ast.IntegerLiteral { + left_val := left_node.val.int() + right_val := right_node.val.int() + match node.op { + .plus { + return ast.IntegerLiteral{ + val: (left_val + right_val).str() + pos: pos + } + } + .mul { + return ast.IntegerLiteral{ + val: (left_val * right_val).str() + pos: pos + } + } + .minus { + return ast.IntegerLiteral{ + val: (left_val - right_val).str() + pos: pos + } + } + .div { + return ast.IntegerLiteral{ + val: (left_val / right_val).str() + pos: pos + } + } + .mod { + return ast.IntegerLiteral{ + val: (left_val % right_val).str() + pos: pos + } + } + .xor { + return ast.IntegerLiteral{ + val: (left_val ^ right_val).str() + pos: pos + } + } + .pipe { + return ast.IntegerLiteral{ + val: (left_val | right_val).str() + pos: pos + } + } + .amp { + return ast.IntegerLiteral{ + val: (left_val & right_val).str() + pos: pos + } + } + else { + return node + } + } + } + else { + return node + } + } + } + else { + return node + } + } +}