v.gen.native: improve error messages for unsupported features (#11253)
							parent
							
								
									c9d6242c6d
								
							
						
					
					
						commit
						82b16453e4
					
				| 
						 | 
				
			
			@ -229,7 +229,7 @@ fn (mut g Gen) mov_reg_to_var(var_offset int, reg Register) {
 | 
			
		|||
		.rsi { g.write8(0x75) }
 | 
			
		||||
		.rdx { g.write8(0x55) }
 | 
			
		||||
		.rcx { g.write8(0x4d) }
 | 
			
		||||
		else { verror('mov_from_reg $reg') }
 | 
			
		||||
		else { g.n_error('mov_from_reg $reg') }
 | 
			
		||||
	}
 | 
			
		||||
	g.write8(0xff - var_offset + 1)
 | 
			
		||||
	g.println('mov DWORD PTR[rbp-$var_offset.hex2()],$reg')
 | 
			
		||||
| 
						 | 
				
			
			@ -251,7 +251,7 @@ fn (mut g Gen) mov_var_to_reg(reg Register, var_offset int) {
 | 
			
		|||
		.rdx { g.write8(0x55) }
 | 
			
		||||
		.rbx { g.write8(0x5d) }
 | 
			
		||||
		.rcx { g.write8(0x4d) }
 | 
			
		||||
		else { verror('mov_var_to_reg $reg') }
 | 
			
		||||
		else { g.n_error('mov_var_to_reg $reg') }
 | 
			
		||||
	}
 | 
			
		||||
	g.write8(0xff - var_offset + 1)
 | 
			
		||||
	g.println('mov $reg,DWORD PTR[rbp-$var_offset.hex2()]')
 | 
			
		||||
| 
						 | 
				
			
			@ -354,7 +354,7 @@ fn (mut g Gen) add8_var(reg Register, var_offset int) {
 | 
			
		|||
	g.write8(0x03)
 | 
			
		||||
	match reg {
 | 
			
		||||
		.eax, .rax { g.write8(0x45) }
 | 
			
		||||
		else { verror('add8_var') }
 | 
			
		||||
		else { g.n_error('add8_var') }
 | 
			
		||||
	}
 | 
			
		||||
	g.write8(0xff - var_offset + 1)
 | 
			
		||||
	g.println('add8 $reg,DWORD PTR[rbp-$var_offset.hex2()]')
 | 
			
		||||
| 
						 | 
				
			
			@ -364,7 +364,7 @@ fn (mut g Gen) sub8_var(reg Register, var_offset int) {
 | 
			
		|||
	g.write8(0x2b)
 | 
			
		||||
	match reg {
 | 
			
		||||
		.eax, .rax { g.write8(0x45) }
 | 
			
		||||
		else { verror('sub8_var') }
 | 
			
		||||
		else { g.n_error('sub8_var') }
 | 
			
		||||
	}
 | 
			
		||||
	g.write8(0xff - var_offset + 1)
 | 
			
		||||
	g.println('sub8 $reg,DWORD PTR[rbp-$var_offset.hex2()]')
 | 
			
		||||
| 
						 | 
				
			
			@ -385,7 +385,7 @@ fn (mut g Gen) mul8_var(reg Register, var_offset int) {
 | 
			
		|||
	g.write8(0xaf)
 | 
			
		||||
	match reg {
 | 
			
		||||
		.eax, .rax { g.write8(0x45) }
 | 
			
		||||
		else { verror('mul8_var') }
 | 
			
		||||
		else { g.n_error('mul8_var') }
 | 
			
		||||
	}
 | 
			
		||||
	g.write8(0xff - var_offset + 1)
 | 
			
		||||
	g.println('mul8 $reg,DWORD PTR[rbp-$var_offset.hex2()]')
 | 
			
		||||
| 
						 | 
				
			
			@ -439,11 +439,11 @@ pub fn (mut g Gen) xor(r Register, v int) {
 | 
			
		|||
				g.println('xor rcx, -1')
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				verror('unhandled xor')
 | 
			
		||||
				g.n_error('unhandled xor')
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		verror('unhandled xor')
 | 
			
		||||
		g.n_error('unhandled xor')
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -495,7 +495,7 @@ fn (mut g Gen) nsyscall_write() int {
 | 
			
		|||
			return 0x2000004
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			verror('unsupported exit syscall for this platform')
 | 
			
		||||
			g.n_error('unsupported exit syscall for this platform')
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0
 | 
			
		||||
| 
						 | 
				
			
			@ -510,7 +510,7 @@ fn (mut g Gen) nsyscall_exit() int {
 | 
			
		|||
			return 0x2000001
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			verror('unsupported exit syscall for this platform')
 | 
			
		||||
			g.n_error('unsupported exit syscall for this platform')
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0
 | 
			
		||||
| 
						 | 
				
			
			@ -525,7 +525,7 @@ pub fn (mut g Gen) gen_amd64_exit(expr ast.Expr) {
 | 
			
		|||
	match expr {
 | 
			
		||||
		ast.CallExpr {
 | 
			
		||||
			right := expr.return_type
 | 
			
		||||
			verror('native exit builtin: Unsupported call $right')
 | 
			
		||||
			g.n_error('native exit builtin: Unsupported call $right')
 | 
			
		||||
		}
 | 
			
		||||
		ast.Ident {
 | 
			
		||||
			var_offset := g.get_var_offset(expr.name)
 | 
			
		||||
| 
						 | 
				
			
			@ -535,7 +535,7 @@ pub fn (mut g Gen) gen_amd64_exit(expr ast.Expr) {
 | 
			
		|||
			g.mov(.edi, expr.val.int())
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			verror('native builtin exit expects a numeric argument')
 | 
			
		||||
			g.n_error('native builtin exit expects a numeric argument')
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	g.mov(.eax, g.nsyscall_exit())
 | 
			
		||||
| 
						 | 
				
			
			@ -560,7 +560,7 @@ fn (mut g Gen) mov(reg Register, val int) {
 | 
			
		|||
				return
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				verror('unhandled mov $reg, -1')
 | 
			
		||||
				g.n_error('unhandled mov $reg, -1')
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -600,7 +600,7 @@ fn (mut g Gen) mov(reg Register, val int) {
 | 
			
		|||
				g.write8(0xe4)
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				verror('unhandled mov $reg, $reg')
 | 
			
		||||
				g.n_error('unhandled mov $reg, $reg')
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		g.println('xor $reg, $reg')
 | 
			
		||||
| 
						 | 
				
			
			@ -627,7 +627,7 @@ fn (mut g Gen) mov(reg Register, val int) {
 | 
			
		|||
				g.write8(0xbc) // r11 is 0xbb etc
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				verror('unhandled mov $reg')
 | 
			
		||||
				g.n_error('unhandled mov $reg')
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		g.write32(val)
 | 
			
		||||
| 
						 | 
				
			
			@ -731,7 +731,7 @@ fn (mut g Gen) mov_reg(a Register, b Register) {
 | 
			
		|||
		g.write8(0x89)
 | 
			
		||||
		g.write8(0xc6)
 | 
			
		||||
	} else {
 | 
			
		||||
		verror('unhandled mov_reg combination for $a $b')
 | 
			
		||||
		g.n_error('unhandled mov_reg combination for $a $b')
 | 
			
		||||
	}
 | 
			
		||||
	g.println('mov $a, $b')
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -757,7 +757,7 @@ pub fn (mut g Gen) call_fn(node ast.CallExpr) {
 | 
			
		|||
	eprintln('call fn ($n)')
 | 
			
		||||
	addr := g.fn_addr[n]
 | 
			
		||||
	if addr == 0 {
 | 
			
		||||
		verror('fn addr of `$name` = 0')
 | 
			
		||||
		g.n_error('fn addr of `$name` = 0')
 | 
			
		||||
	}
 | 
			
		||||
	// Copy values to registers (calling convention)
 | 
			
		||||
	// g.mov(.eax, 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -778,12 +778,12 @@ pub fn (mut g Gen) call_fn(node ast.CallExpr) {
 | 
			
		|||
				g.mov_var_to_reg(native.fn_arg_registers[i], var_offset)
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				verror('unhandled call_fn (name=$name) node: ' + expr.type_name())
 | 
			
		||||
				g.v_error('unhandled call_fn (name=$name) node: $expr.type_name()', node.pos)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if node.args.len > 6 {
 | 
			
		||||
		verror('more than 6 args not allowed for now')
 | 
			
		||||
		g.v_error('more than 6 args not allowed for now', node.pos)
 | 
			
		||||
	}
 | 
			
		||||
	g.call(int(addr))
 | 
			
		||||
	g.println('fn call `${name}()`')
 | 
			
		||||
| 
						 | 
				
			
			@ -835,7 +835,10 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
 | 
			
		|||
						match node.left_types[i] {
 | 
			
		||||
							7 { // ast.IndexExpr {
 | 
			
		||||
								ie := node.left[i] as ast.IndexExpr
 | 
			
		||||
								bracket := name.index('[') or { verror('bracket expected') }
 | 
			
		||||
								bracket := name.index('[') or {
 | 
			
		||||
									g.v_error('bracket expected', node.pos)
 | 
			
		||||
									exit(1)
 | 
			
		||||
								}
 | 
			
		||||
								var_name := name[0..bracket]
 | 
			
		||||
								mut dest := g.get_var_offset(var_name)
 | 
			
		||||
								index := ie.index as ast.IntegerLiteral
 | 
			
		||||
| 
						 | 
				
			
			@ -848,7 +851,7 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
 | 
			
		|||
							else {
 | 
			
		||||
								tn := node.left[i].type_name()
 | 
			
		||||
								dump(node.left_types)
 | 
			
		||||
								verror('unhandled assign type: $tn')
 | 
			
		||||
								g.n_error('unhandled assign type: $tn')
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
| 
						 | 
				
			
			@ -935,7 +938,7 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
 | 
			
		|||
						}
 | 
			
		||||
						else {
 | 
			
		||||
							dump(e)
 | 
			
		||||
							verror('unhandled array init type')
 | 
			
		||||
							g.n_error('unhandled array init type')
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -960,7 +963,7 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
 | 
			
		|||
					g.mov_var_to_reg(.rax, dest)
 | 
			
		||||
					g.add_reg(.rax, .rdi)
 | 
			
		||||
				} else {
 | 
			
		||||
					verror('only integers and idents can be used as indexes')
 | 
			
		||||
					g.n_error('only integers and idents can be used as indexes')
 | 
			
		||||
				}
 | 
			
		||||
				// TODO check if out of bounds access
 | 
			
		||||
				g.mov_reg_to_var(offset, .eax)
 | 
			
		||||
| 
						 | 
				
			
			@ -977,10 +980,12 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
 | 
			
		|||
				g.mov_reg_to_var(dest, .rax)
 | 
			
		||||
				g.mov_var_to_reg(.rsi, dest)
 | 
			
		||||
			}
 | 
			
		||||
			ast.GoExpr {
 | 
			
		||||
				g.v_error('threads not implemented for the native backend', node.pos)
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				// dump(node)
 | 
			
		||||
				g.error_with_pos('native assign_stmt unhandled expr: ' + right.type_name(),
 | 
			
		||||
					right.position())
 | 
			
		||||
				g.v_error('unhandled assign_stmt expression: $right.type_name()', right.position())
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		// }
 | 
			
		||||
| 
						 | 
				
			
			@ -993,7 +998,7 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
 | 
			
		|||
	}
 | 
			
		||||
	// TODO
 | 
			
		||||
	if node.left is ast.InfixExpr {
 | 
			
		||||
		verror('only simple expressions are supported right now (not more than 2 operands)')
 | 
			
		||||
		g.n_error('only simple expressions are supported right now (not more than 2 operands)')
 | 
			
		||||
	}
 | 
			
		||||
	match mut node.left {
 | 
			
		||||
		ast.Ident {
 | 
			
		||||
| 
						 | 
				
			
			@ -1028,7 +1033,7 @@ fn (mut g Gen) gen_assert(assert_node ast.AssertStmt) {
 | 
			
		|||
	} else if ane is ast.InfixExpr { // assert 1==1
 | 
			
		||||
		ine = ane
 | 
			
		||||
	} else {
 | 
			
		||||
		verror('Unsupported expression in assert')
 | 
			
		||||
		g.n_error('Unsupported expression in assert')
 | 
			
		||||
	}
 | 
			
		||||
	cjmp_addr = g.condition(ine, true)
 | 
			
		||||
	g.expr(assert_node.expr)
 | 
			
		||||
| 
						 | 
				
			
			@ -1094,10 +1099,10 @@ fn (mut g Gen) condition(infix_expr ast.InfixExpr, neg bool) int {
 | 
			
		|||
					// lit := infix_expr.right as ast.IntegerLiteral
 | 
			
		||||
					// g.cmp_var(infix_expr.left.name, lit.val.int())
 | 
			
		||||
					// +not
 | 
			
		||||
					verror('unsupported if construction')
 | 
			
		||||
					g.n_error('unsupported if construction')
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					verror('unsupported if construction')
 | 
			
		||||
					g.n_error('unsupported if construction')
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -1110,16 +1115,16 @@ fn (mut g Gen) condition(infix_expr ast.InfixExpr, neg bool) int {
 | 
			
		|||
				}
 | 
			
		||||
				ast.Ident {
 | 
			
		||||
					// var < var2
 | 
			
		||||
					verror('unsupported if construction')
 | 
			
		||||
					g.n_error('unsupported if construction')
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					verror('unsupported if construction')
 | 
			
		||||
					g.n_error('unsupported if construction')
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			dump(infix_expr)
 | 
			
		||||
			verror('unhandled infix.left')
 | 
			
		||||
			// dump(infix_expr)
 | 
			
		||||
			g.n_error('unhandled $infix_expr.left')
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1131,6 +1136,9 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
 | 
			
		|||
	branch := node.branches[0]
 | 
			
		||||
	infix_expr := branch.cond as ast.InfixExpr
 | 
			
		||||
	cjmp_addr := g.condition(infix_expr, false)
 | 
			
		||||
	if node.is_comptime {
 | 
			
		||||
		g.n_error('ignored comptime')
 | 
			
		||||
	}
 | 
			
		||||
	g.stmts(branch.stmts)
 | 
			
		||||
	// Now that we know where we need to jump if the condition is false, update the `jne` call.
 | 
			
		||||
	// The value is the relative address, difference between current position and the location
 | 
			
		||||
| 
						 | 
				
			
			@ -1139,7 +1147,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
 | 
			
		|||
	g.write32_at(cjmp_addr, int(g.pos() - cjmp_addr - 4)) // 4 is for "00 00 00 00"
 | 
			
		||||
 | 
			
		||||
	if node.has_else {
 | 
			
		||||
		verror('else statements not yet supported')
 | 
			
		||||
		g.n_error('else statements not yet supported')
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1155,7 +1163,7 @@ fn (mut g Gen) for_stmt(node ast.ForStmt) {
 | 
			
		|||
			jump_addr = g.cjmp(.jge)
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			verror('unhandled infix.left')
 | 
			
		||||
			g.n_error('unhandled infix.left')
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	g.stmts(node.stmts)
 | 
			
		||||
| 
						 | 
				
			
			@ -1256,7 +1264,7 @@ pub fn (mut g Gen) allocate_var(name string, size int, initial_val int) int {
 | 
			
		|||
			g.write8(0x45)
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			verror('allocate_var: bad size $size')
 | 
			
		||||
			g.n_error('allocate_var: bad size $size')
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// Generate N in `[rbp-N]`
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,7 +61,7 @@ fn (mut g Gen) mov_arm(reg Arm64Register, val u64) {
 | 
			
		|||
		g.write32(0xd2800000 + int(r) + (int(val) << 5))
 | 
			
		||||
		g.println('mov x$r, $val')
 | 
			
		||||
	} else {
 | 
			
		||||
		verror('mov_arm unsupported values')
 | 
			
		||||
		g.n_error('mov_arm unsupported values')
 | 
			
		||||
	}
 | 
			
		||||
	/*
 | 
			
		||||
	if 1 ^ (x & ~m) != 0 {
 | 
			
		||||
| 
						 | 
				
			
			@ -87,7 +87,7 @@ pub fn (mut g Gen) call_fn_arm64(node ast.CallExpr) {
 | 
			
		|||
	// println('call fn $name')
 | 
			
		||||
	addr := g.fn_addr[name]
 | 
			
		||||
	if addr == 0 {
 | 
			
		||||
		verror('fn addr of `$name` = 0')
 | 
			
		||||
		g.n_error('fn addr of `$name` = 0')
 | 
			
		||||
	}
 | 
			
		||||
	// Copy values to registers (calling convention)
 | 
			
		||||
	// g.mov_arm(.eax, 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -110,12 +110,12 @@ pub fn (mut g Gen) call_fn_arm64(node ast.CallExpr) {
 | 
			
		|||
			}
 | 
			
		||||
			*/
 | 
			
		||||
			else {
 | 
			
		||||
				verror('unhandled call_fn (name=$name) node: ' + expr.type_name())
 | 
			
		||||
				g.n_error('unhandled call_fn (name=$name) node: ' + expr.type_name())
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if node.args.len > 6 {
 | 
			
		||||
		verror('more than 6 args not allowed for now')
 | 
			
		||||
		g.n_error('more than 6 args not allowed for now')
 | 
			
		||||
	}
 | 
			
		||||
	g.call(int(addr))
 | 
			
		||||
	g.println('fn call `${name}()`')
 | 
			
		||||
| 
						 | 
				
			
			@ -165,7 +165,7 @@ pub fn (mut c Arm64) gen_exit(mut g Gen, expr ast.Expr) {
 | 
			
		|||
			return_code = expr.val.u64()
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			verror('native builtin exit expects a numeric argument')
 | 
			
		||||
			g.n_error('native builtin exit expects a numeric argument')
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	match c.g.pref.os {
 | 
			
		||||
| 
						 | 
				
			
			@ -179,7 +179,7 @@ pub fn (mut c Arm64) gen_exit(mut g Gen, expr ast.Expr) {
 | 
			
		|||
			c.g.mov_arm(.x0, 0)
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			verror('unsupported os $c.g.pref.os')
 | 
			
		||||
			g.n_error('unsupported os $c.g.pref.os')
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	g.svc()
 | 
			
		||||
| 
						 | 
				
			
			@ -191,7 +191,7 @@ pub fn (mut g Gen) gen_arm64_exit(expr ast.Expr) {
 | 
			
		|||
			g.mov_arm(.x16, expr.val.u64())
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			verror('native builtin exit expects a numeric argument')
 | 
			
		||||
			g.n_error('native builtin exit expects a numeric argument')
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	g.mov_arm(.x0, 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -87,7 +87,7 @@ pub fn gen(files []&ast.File, table &ast.Table, out_name string, pref &pref.Pref
 | 
			
		|||
			eprintln('Warning: ${file.warnings[0]}')
 | 
			
		||||
		}
 | 
			
		||||
		if file.errors.len > 0 {
 | 
			
		||||
			verror('Error ${file.errors[0]}')
 | 
			
		||||
			g.n_error(file.errors[0].str())
 | 
			
		||||
		}
 | 
			
		||||
		g.stmts(file.stmts)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -109,7 +109,7 @@ pub fn (mut g Gen) generate_header() {
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			verror('Error: only `raw`, `linux` and `macos` are supported for -os in -native')
 | 
			
		||||
			g.n_error('only `raw`, `linux` and `macos` are supported for -os in -native')
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -222,7 +222,7 @@ fn (mut g Gen) write_string_with_padding(s string, max int) {
 | 
			
		|||
fn (mut g Gen) get_var_offset(var_name string) int {
 | 
			
		||||
	offset := g.var_offset[var_name]
 | 
			
		||||
	if offset == 0 {
 | 
			
		||||
		verror('unknown variable `$var_name`')
 | 
			
		||||
		g.n_error('unknown variable `$var_name`')
 | 
			
		||||
	}
 | 
			
		||||
	return offset
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -249,7 +249,7 @@ pub fn (mut g Gen) gen_print_from_expr(expr ast.Expr, name string) {
 | 
			
		|||
		else {
 | 
			
		||||
			dump(typeof(expr).name)
 | 
			
		||||
			dump(expr)
 | 
			
		||||
			verror('expected string as argument for print')
 | 
			
		||||
			g.n_error('expected string as argument for print')
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -268,7 +268,7 @@ fn (mut g Gen) println(comment string) {
 | 
			
		|||
	addr := g.debug_pos.hex()
 | 
			
		||||
	// println('$g.debug_pos "$addr"')
 | 
			
		||||
	print(term.red(strings.repeat(`0`, 6 - addr.len) + addr + '  '))
 | 
			
		||||
	for i := g.debug_pos; i < g.buf.len; i++ {
 | 
			
		||||
	for i := g.debug_pos; i < g.pos(); i++ {
 | 
			
		||||
		s := g.buf[i].hex()
 | 
			
		||||
		if s.len == 1 {
 | 
			
		||||
			print(term.blue('0'))
 | 
			
		||||
| 
						 | 
				
			
			@ -282,7 +282,7 @@ fn (mut g Gen) println(comment string) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g Gen) for_in_stmt(node ast.ForInStmt) {
 | 
			
		||||
	verror('for-in statement is not yet implemented')
 | 
			
		||||
	g.v_error('for-in statement is not yet implemented', node.pos)
 | 
			
		||||
	/*
 | 
			
		||||
	if node.is_range {
 | 
			
		||||
		// `for x in 1..10 {`
 | 
			
		||||
| 
						 | 
				
			
			@ -332,7 +332,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
 | 
			
		|||
			words := node.val.split(' ')
 | 
			
		||||
			for word in words {
 | 
			
		||||
				if word.len != 2 {
 | 
			
		||||
					verror('opcodes format: xx xx xx xx')
 | 
			
		||||
					g.n_error('opcodes format: xx xx xx xx')
 | 
			
		||||
				}
 | 
			
		||||
				b := unsafe { C.strtol(&char(word.str), 0, 16) }
 | 
			
		||||
				// b := word.byte()
 | 
			
		||||
| 
						 | 
				
			
			@ -346,24 +346,27 @@ fn (mut g Gen) stmt(node ast.Stmt) {
 | 
			
		|||
			// if in main
 | 
			
		||||
			// zero := ast.IntegerLiteral{}
 | 
			
		||||
			// g.gen_exit(zero)
 | 
			
		||||
			dump(node)
 | 
			
		||||
			dump(node.types)
 | 
			
		||||
			// dump(node)
 | 
			
		||||
			// dump(node.types)
 | 
			
		||||
			mut s := '?' //${node.exprs[0].val.str()}'
 | 
			
		||||
			e0 := node.exprs[0]
 | 
			
		||||
			match e0 {
 | 
			
		||||
				ast.IntegerLiteral {
 | 
			
		||||
					g.mov64(.rax, e0.val.int())
 | 
			
		||||
				}
 | 
			
		||||
				ast.InfixExpr {
 | 
			
		||||
					// TODO
 | 
			
		||||
					// verror('expr')
 | 
			
		||||
				}
 | 
			
		||||
				ast.StringLiteral {
 | 
			
		||||
					s = e0.val.str()
 | 
			
		||||
					eprintln('jlalala $s')
 | 
			
		||||
					g.expr(node.exprs[0])
 | 
			
		||||
					g.mov64(.rax, g.allocate_string(s, 2))
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					verror('unknown return type')
 | 
			
		||||
					g.n_error('unknown return type $e0')
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			g.expr(node.exprs[0])
 | 
			
		||||
			g.mov64(.rax, g.allocate_string(s, 2))
 | 
			
		||||
			// intel specific
 | 
			
		||||
			g.add8(.rsp, 0x20) // XXX depends on scope frame size
 | 
			
		||||
			g.pop(.rbp)
 | 
			
		||||
| 
						 | 
				
			
			@ -387,7 +390,7 @@ fn (mut g Gen) expr(node ast.Expr) {
 | 
			
		|||
			g.expr(node.expr)
 | 
			
		||||
		}
 | 
			
		||||
		ast.ArrayInit {
 | 
			
		||||
			verror('array init expr not supported yet')
 | 
			
		||||
			g.n_error('array init expr not supported yet')
 | 
			
		||||
		}
 | 
			
		||||
		ast.BoolLiteral {}
 | 
			
		||||
		ast.CallExpr {
 | 
			
		||||
| 
						 | 
				
			
			@ -403,7 +406,11 @@ fn (mut g Gen) expr(node ast.Expr) {
 | 
			
		|||
		ast.FloatLiteral {}
 | 
			
		||||
		ast.Ident {}
 | 
			
		||||
		ast.IfExpr {
 | 
			
		||||
			g.if_expr(node)
 | 
			
		||||
			if node.is_comptime {
 | 
			
		||||
				eprintln('Warning: ignored compile time conditional not yet supported for the native backend.')
 | 
			
		||||
			} else {
 | 
			
		||||
				g.if_expr(node)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		ast.InfixExpr {}
 | 
			
		||||
		ast.IntegerLiteral {}
 | 
			
		||||
| 
						 | 
				
			
			@ -412,8 +419,11 @@ fn (mut g Gen) expr(node ast.Expr) {
 | 
			
		|||
		}
 | 
			
		||||
		ast.StringLiteral {}
 | 
			
		||||
		ast.StructInit {}
 | 
			
		||||
		ast.GoExpr {
 | 
			
		||||
			g.v_error('native backend doesnt support threads yet', node.pos) // token.Position{})
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			println(term.red('native.expr(): unhandled node: ' + node.type_name()))
 | 
			
		||||
			g.n_error('expr: unhandled node type: $node.type_name()')
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -436,11 +446,11 @@ fn (mut g Gen) postfix_expr(node ast.PostfixExpr) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
[noreturn]
 | 
			
		||||
fn verror(s string) {
 | 
			
		||||
	util.verror('native gen error', s)
 | 
			
		||||
pub fn (mut g Gen) n_error(s string) {
 | 
			
		||||
	util.verror('native error', s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (mut g Gen) error_with_pos(s string, pos token.Position) {
 | 
			
		||||
pub fn (mut g Gen) v_error(s string, pos token.Position) {
 | 
			
		||||
	// TODO: store a file index in the Position too,
 | 
			
		||||
	// so that the file path can be retrieved from the pos, instead
 | 
			
		||||
	// of guessed from the pref.path ...
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue