v: add constant folding AST transformation (#11085)
							parent
							
								
									ec39e38e14
								
							
						
					
					
						commit
						cf0767ad6c
					
				|  | @ -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 { | ||||
|  |  | |||
|  | @ -0,0 +1 @@ | |||
| int zzz = 579 | ||||
|  | @ -0,0 +1 @@ | |||
| 579 | ||||
|  | @ -0,0 +1,4 @@ | |||
| fn main() { | ||||
|   zzz := 123 + 456 | ||||
|   println(zzz) | ||||
| } | ||||
|  | @ -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 | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
		Loading…
	
		Reference in New Issue