ast, parser: implement simple AST poisoning (#9525)
parent
999c385b7f
commit
b319068151
|
@ -14,14 +14,14 @@ pub type Expr = AnonFn | ArrayDecompose | ArrayInit | AsCast | Assoc | AtExpr |
|
||||||
CTempVar | CallExpr | CastExpr | ChanInit | CharLiteral | Comment | ComptimeCall |
|
CTempVar | CallExpr | CastExpr | ChanInit | CharLiteral | Comment | ComptimeCall |
|
||||||
ComptimeSelector | ConcatExpr | DumpExpr | EnumVal | FloatLiteral | GoExpr | Ident |
|
ComptimeSelector | ConcatExpr | DumpExpr | EnumVal | FloatLiteral | GoExpr | Ident |
|
||||||
IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr |
|
IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr |
|
||||||
MapInit | MatchExpr | None | OffsetOf | OrExpr | ParExpr | PostfixExpr | PrefixExpr |
|
MapInit | MatchExpr | NodeError | None | OffsetOf | OrExpr | ParExpr | PostfixExpr |
|
||||||
RangeExpr | SelectExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral | StringLiteral |
|
PrefixExpr | RangeExpr | SelectExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral |
|
||||||
StructInit | Type | TypeOf | UnsafeExpr
|
StringLiteral | StructInit | Type | TypeOf | UnsafeExpr
|
||||||
|
|
||||||
pub type Stmt = AsmStmt | AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDecl |
|
pub type Stmt = AsmStmt | AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDecl |
|
||||||
DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl |
|
DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl |
|
||||||
GoStmt | GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | Return |
|
GoStmt | GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | NodeError |
|
||||||
SqlStmt | StructDecl | TypeDecl
|
Return | SqlStmt | StructDecl | TypeDecl
|
||||||
|
|
||||||
// NB: when you add a new Expr or Stmt type with a .pos field, remember to update
|
// NB: when you add a new Expr or Stmt type with a .pos field, remember to update
|
||||||
// the .position() token.Position methods too.
|
// the .position() token.Position methods too.
|
||||||
|
@ -1083,7 +1083,7 @@ pub:
|
||||||
pub struct AsmAddressing {
|
pub struct AsmAddressing {
|
||||||
pub:
|
pub:
|
||||||
displacement u32 // 8, 16 or 32 bit literal value
|
displacement u32 // 8, 16 or 32 bit literal value
|
||||||
scale int = -1 // 1, 2, 4, or 8 literal
|
scale int = -1 // 1, 2, 4, or 8 literal
|
||||||
mode AddressingMode
|
mode AddressingMode
|
||||||
pos token.Position
|
pos token.Position
|
||||||
pub mut:
|
pub mut:
|
||||||
|
@ -1408,6 +1408,12 @@ pub mut:
|
||||||
sub_structs map[int]SqlExpr
|
sub_structs map[int]SqlExpr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct NodeError {
|
||||||
|
pub:
|
||||||
|
idx int // index for referencing the related ast.File error
|
||||||
|
pos token.Position
|
||||||
|
}
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
pub fn (expr Expr) is_blank_ident() bool {
|
pub fn (expr Expr) is_blank_ident() bool {
|
||||||
match expr {
|
match expr {
|
||||||
|
@ -1422,12 +1428,12 @@ pub fn (expr Expr) position() token.Position {
|
||||||
AnonFn {
|
AnonFn {
|
||||||
return expr.decl.pos
|
return expr.decl.pos
|
||||||
}
|
}
|
||||||
ArrayDecompose, ArrayInit, AsCast, Assoc, AtExpr, BoolLiteral, CallExpr, CastExpr, ChanInit,
|
NodeError, ArrayDecompose, ArrayInit, AsCast, Assoc, AtExpr, BoolLiteral, CallExpr, CastExpr,
|
||||||
CharLiteral, ConcatExpr, Comment, ComptimeCall, ComptimeSelector, EnumVal, DumpExpr, FloatLiteral,
|
ChanInit, CharLiteral, ConcatExpr, Comment, ComptimeCall, ComptimeSelector, EnumVal, DumpExpr,
|
||||||
GoExpr, Ident, IfExpr, IndexExpr, IntegerLiteral, Likely, LockExpr, MapInit, MatchExpr,
|
FloatLiteral, GoExpr, Ident, IfExpr, IndexExpr, IntegerLiteral, Likely, LockExpr, MapInit,
|
||||||
None, OffsetOf, OrExpr, ParExpr, PostfixExpr, PrefixExpr, RangeExpr, SelectExpr, SelectorExpr,
|
MatchExpr, None, OffsetOf, OrExpr, ParExpr, PostfixExpr, PrefixExpr, RangeExpr, SelectExpr,
|
||||||
SizeOf, SqlExpr, StringInterLiteral, StringLiteral, StructInit, Type, TypeOf, UnsafeExpr
|
SelectorExpr, SizeOf, SqlExpr, StringInterLiteral, StringLiteral, StructInit, Type, TypeOf,
|
||||||
{
|
UnsafeExpr {
|
||||||
return expr.pos
|
return expr.pos
|
||||||
}
|
}
|
||||||
IfGuardExpr {
|
IfGuardExpr {
|
||||||
|
|
|
@ -3324,6 +3324,7 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||||
}
|
}
|
||||||
// c.expected_type = table.void_type
|
// c.expected_type = table.void_type
|
||||||
match mut node {
|
match mut node {
|
||||||
|
ast.NodeError {}
|
||||||
ast.AsmStmt {
|
ast.AsmStmt {
|
||||||
c.asm_stmt(mut node)
|
c.asm_stmt(mut node)
|
||||||
}
|
}
|
||||||
|
@ -3950,6 +3951,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
match mut node {
|
match mut node {
|
||||||
|
ast.NodeError {}
|
||||||
ast.CTempVar {
|
ast.CTempVar {
|
||||||
return node.typ
|
return node.typ
|
||||||
}
|
}
|
||||||
|
|
|
@ -382,6 +382,7 @@ pub fn (mut f Fmt) stmt(node ast.Stmt) {
|
||||||
eprintln('stmt: ${node.pos:-42} | node: ${node.type_name():-20}')
|
eprintln('stmt: ${node.pos:-42} | node: ${node.type_name():-20}')
|
||||||
}
|
}
|
||||||
match node {
|
match node {
|
||||||
|
ast.NodeError {}
|
||||||
ast.AsmStmt {
|
ast.AsmStmt {
|
||||||
f.asm_stmt(node)
|
f.asm_stmt(node)
|
||||||
}
|
}
|
||||||
|
@ -480,6 +481,7 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
|
||||||
eprintln('expr: ${node.position():-42} | node: ${node.type_name():-20} | $node.str()')
|
eprintln('expr: ${node.position():-42} | node: ${node.type_name():-20} | $node.str()')
|
||||||
}
|
}
|
||||||
match mut node {
|
match mut node {
|
||||||
|
ast.NodeError {}
|
||||||
ast.AnonFn {
|
ast.AnonFn {
|
||||||
f.fn_decl(node.decl)
|
f.fn_decl(node.decl)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1187,6 +1187,7 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
// g.cur_mod = node.name
|
// g.cur_mod = node.name
|
||||||
g.cur_mod = node
|
g.cur_mod = node
|
||||||
}
|
}
|
||||||
|
ast.NodeError {}
|
||||||
ast.Return {
|
ast.Return {
|
||||||
g.write_defer_stmts_when_needed()
|
g.write_defer_stmts_when_needed()
|
||||||
// af := g.autofree && node.exprs.len > 0 && node.exprs[0] is ast.CallExpr && !g.is_builtin_mod
|
// af := g.autofree && node.exprs.len > 0 && node.exprs[0] is ast.CallExpr && !g.is_builtin_mod
|
||||||
|
@ -3013,6 +3014,7 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
ast.MapInit {
|
ast.MapInit {
|
||||||
g.map_init(node)
|
g.map_init(node)
|
||||||
}
|
}
|
||||||
|
ast.NodeError {}
|
||||||
ast.None {
|
ast.None {
|
||||||
g.write('_const_none__')
|
g.write('_const_none__')
|
||||||
}
|
}
|
||||||
|
|
|
@ -427,6 +427,7 @@ fn (mut g JsGen) stmt(node ast.Stmt) {
|
||||||
ast.Module {
|
ast.Module {
|
||||||
// skip: namespacing implemented externally
|
// skip: namespacing implemented externally
|
||||||
}
|
}
|
||||||
|
ast.NodeError {}
|
||||||
ast.Return {
|
ast.Return {
|
||||||
if g.defer_stmts.len > 0 {
|
if g.defer_stmts.len > 0 {
|
||||||
g.gen_defer_stmts()
|
g.gen_defer_stmts()
|
||||||
|
@ -445,6 +446,7 @@ fn (mut g JsGen) stmt(node ast.Stmt) {
|
||||||
|
|
||||||
fn (mut g JsGen) expr(node ast.Expr) {
|
fn (mut g JsGen) expr(node ast.Expr) {
|
||||||
match node {
|
match node {
|
||||||
|
ast.NodeError {}
|
||||||
ast.CTempVar {
|
ast.CTempVar {
|
||||||
g.write('/* ast.CTempVar: node.name */')
|
g.write('/* ast.CTempVar: node.name */')
|
||||||
}
|
}
|
||||||
|
@ -693,7 +695,7 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt) {
|
||||||
} else {
|
} else {
|
||||||
g.write(' $op ')
|
g.write(' $op ')
|
||||||
// TODO: Multiple types??
|
// TODO: Multiple types??
|
||||||
should_cast :=
|
should_cast :=
|
||||||
(g.table.type_kind(stmt.left_types.first()) in js.shallow_equatables)
|
(g.table.type_kind(stmt.left_types.first()) in js.shallow_equatables)
|
||||||
&& (g.cast_stack.len <= 0 || stmt.left_types.first() != g.cast_stack.last())
|
&& (g.cast_stack.len <= 0 || stmt.left_types.first() != g.cast_stack.last())
|
||||||
|
|
||||||
|
|
|
@ -123,6 +123,7 @@ pub fn (mut w Walker) stmt(node ast.Stmt) {
|
||||||
ast.InterfaceDecl {}
|
ast.InterfaceDecl {}
|
||||||
ast.Module {}
|
ast.Module {}
|
||||||
ast.TypeDecl {}
|
ast.TypeDecl {}
|
||||||
|
ast.NodeError {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,6 +336,7 @@ fn (mut w Walker) expr(node ast.Expr) {
|
||||||
ast.UnsafeExpr {
|
ast.UnsafeExpr {
|
||||||
w.expr(node.expr)
|
w.expr(node.expr)
|
||||||
}
|
}
|
||||||
|
ast.NodeError {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,8 +110,7 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
|
||||||
// a, b := a + 1, b
|
// a, b := a + 1, b
|
||||||
for r in right {
|
for r in right {
|
||||||
p.check_undefined_variables(left, r) or {
|
p.check_undefined_variables(left, r) or {
|
||||||
p.error('check_undefined_variables failed')
|
return p.error('check_undefined_variables failed')
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if left.len > 1 {
|
} else if left.len > 1 {
|
||||||
|
@ -119,8 +118,8 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
|
||||||
for r in right {
|
for r in right {
|
||||||
has_cross_var = p.check_cross_variables(left, r)
|
has_cross_var = p.check_cross_variables(left, r)
|
||||||
if op !in [.assign, .decl_assign] {
|
if op !in [.assign, .decl_assign] {
|
||||||
p.error_with_pos('unexpected $op.str(), expecting := or = or comma', pos)
|
return p.error_with_pos('unexpected $op.str(), expecting := or = or comma',
|
||||||
return ast.Stmt{}
|
pos)
|
||||||
}
|
}
|
||||||
if has_cross_var {
|
if has_cross_var {
|
||||||
break
|
break
|
||||||
|
@ -133,8 +132,7 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
if op == .decl_assign {
|
if op == .decl_assign {
|
||||||
if p.scope.known_var(lx.name) {
|
if p.scope.known_var(lx.name) {
|
||||||
p.error_with_pos('redefinition of `$lx.name`', lx.pos)
|
return p.error_with_pos('redefinition of `$lx.name`', lx.pos)
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
mut share := table.ShareType(0)
|
mut share := table.ShareType(0)
|
||||||
if lx.info is ast.IdentVar {
|
if lx.info is ast.IdentVar {
|
||||||
|
@ -142,9 +140,8 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
|
||||||
share = iv.share
|
share = iv.share
|
||||||
if iv.is_static {
|
if iv.is_static {
|
||||||
if !p.pref.translated && !p.pref.is_fmt && !p.inside_unsafe_fn {
|
if !p.pref.translated && !p.pref.is_fmt && !p.inside_unsafe_fn {
|
||||||
p.error_with_pos('static variables are supported only in -translated mode or in [unsafe] fn',
|
return p.error_with_pos('static variables are supported only in -translated mode or in [unsafe] fn',
|
||||||
lx.pos)
|
lx.pos)
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
is_static = true
|
is_static = true
|
||||||
}
|
}
|
||||||
|
@ -175,9 +172,8 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
|
||||||
}
|
}
|
||||||
ast.IndexExpr {
|
ast.IndexExpr {
|
||||||
if op == .decl_assign {
|
if op == .decl_assign {
|
||||||
p.error_with_pos('non-name `$lx.left[$lx.index]` on left side of `:=`',
|
return p.error_with_pos('non-name `$lx.left[$lx.index]` on left side of `:=`',
|
||||||
lx.pos)
|
lx.pos)
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
lx.is_setter = true
|
lx.is_setter = true
|
||||||
}
|
}
|
||||||
|
@ -185,9 +181,8 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
|
||||||
ast.PrefixExpr {}
|
ast.PrefixExpr {}
|
||||||
ast.SelectorExpr {
|
ast.SelectorExpr {
|
||||||
if op == .decl_assign {
|
if op == .decl_assign {
|
||||||
p.error_with_pos('struct fields can only be declared during the initialization',
|
return p.error_with_pos('struct fields can only be declared during the initialization',
|
||||||
lx.pos)
|
lx.pos)
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -12,8 +12,7 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||||
p.open_scope()
|
p.open_scope()
|
||||||
p.inside_for = true
|
p.inside_for = true
|
||||||
if p.tok.kind == .key_match {
|
if p.tok.kind == .key_match {
|
||||||
p.error('cannot use `match` in `for` loop')
|
return p.error('cannot use `match` in `for` loop')
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
// defer { p.close_scope() }
|
// defer { p.close_scope() }
|
||||||
// Infinite loop
|
// Infinite loop
|
||||||
|
@ -34,8 +33,7 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||||
&& p.peek_token(2).kind != .key_mut && p.peek_token(3).kind != .key_in) {
|
&& p.peek_token(2).kind != .key_mut && p.peek_token(3).kind != .key_in) {
|
||||||
// `for i := 0; i < 10; i++ {` or `for a,b := 0,1; a < 10; a++ {`
|
// `for i := 0; i < 10; i++ {` or `for a,b := 0,1; a < 10; a++ {`
|
||||||
if p.tok.kind == .key_mut {
|
if p.tok.kind == .key_mut {
|
||||||
p.error('`mut` is not needed in `for ;;` loops: use `for i := 0; i < n; i ++ {`')
|
return p.error('`mut` is not needed in `for ;;` loops: use `for i := 0; i < n; i ++ {`')
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
mut init := ast.Stmt{}
|
mut init := ast.Stmt{}
|
||||||
mut cond := p.new_true_expr()
|
mut cond := p.new_true_expr()
|
||||||
|
@ -55,8 +53,7 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||||
if p.tok.kind != .semicolon {
|
if p.tok.kind != .semicolon {
|
||||||
// Disallow `for i := 0; i++; i < ...`
|
// Disallow `for i := 0; i++; i < ...`
|
||||||
if p.tok.kind == .name && p.peek_tok.kind in [.inc, .dec] {
|
if p.tok.kind == .name && p.peek_tok.kind in [.inc, .dec] {
|
||||||
p.error('cannot use $p.tok.lit$p.peek_tok.kind as value')
|
return p.error('cannot use $p.tok.lit$p.peek_tok.kind as value')
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
cond = p.expr(0)
|
cond = p.expr(0)
|
||||||
has_cond = true
|
has_cond = true
|
||||||
|
@ -112,16 +109,14 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||||
val_var_pos = p.tok.position()
|
val_var_pos = p.tok.position()
|
||||||
val_var_name = p.check_name()
|
val_var_name = p.check_name()
|
||||||
if key_var_name == val_var_name && key_var_name != '_' {
|
if key_var_name == val_var_name && key_var_name != '_' {
|
||||||
p.error_with_pos('key and value in a for loop cannot be the same', val_var_pos)
|
return p.error_with_pos('key and value in a for loop cannot be the same',
|
||||||
return ast.Stmt{}
|
val_var_pos)
|
||||||
}
|
}
|
||||||
if p.scope.known_var(key_var_name) {
|
if p.scope.known_var(key_var_name) {
|
||||||
p.error('redefinition of key iteration variable `$key_var_name`')
|
return p.error('redefinition of key iteration variable `$key_var_name`')
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
if p.scope.known_var(val_var_name) {
|
if p.scope.known_var(val_var_name) {
|
||||||
p.error('redefinition of value iteration variable `$val_var_name`')
|
return p.error('redefinition of value iteration variable `$val_var_name`')
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
p.scope.register(ast.Var{
|
p.scope.register(ast.Var{
|
||||||
name: key_var_name
|
name: key_var_name
|
||||||
|
@ -130,13 +125,11 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||||
is_tmp: true
|
is_tmp: true
|
||||||
})
|
})
|
||||||
} else if p.scope.known_var(val_var_name) {
|
} else if p.scope.known_var(val_var_name) {
|
||||||
p.error('redefinition of value iteration variable `$val_var_name`')
|
return p.error('redefinition of value iteration variable `$val_var_name`')
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
p.check(.key_in)
|
p.check(.key_in)
|
||||||
if p.tok.kind == .name && p.tok.lit in [key_var_name, val_var_name] {
|
if p.tok.kind == .name && p.tok.lit in [key_var_name, val_var_name] {
|
||||||
p.error('in a `for x in array` loop, the key or value iteration variable `$p.tok.lit` can not be the same as the array variable')
|
return p.error('in a `for x in array` loop, the key or value iteration variable `$p.tok.lit` can not be the same as the array variable')
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
// arr_expr
|
// arr_expr
|
||||||
cond := p.expr(0)
|
cond := p.expr(0)
|
||||||
|
@ -156,8 +149,8 @@ fn (mut p Parser) for_stmt() ast.Stmt {
|
||||||
is_tmp: true
|
is_tmp: true
|
||||||
})
|
})
|
||||||
if key_var_name.len > 0 {
|
if key_var_name.len > 0 {
|
||||||
p.error_with_pos('cannot declare index variable with range `for`', key_var_pos)
|
return p.error_with_pos('cannot declare index variable with range `for`',
|
||||||
return ast.Stmt{}
|
key_var_pos)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// this type will be set in checker
|
// this type will be set in checker
|
||||||
|
|
|
@ -516,8 +516,7 @@ pub fn (mut p Parser) top_stmt() ast.Stmt {
|
||||||
return p.type_decl()
|
return p.type_decl()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p.error('wrong pub keyword usage')
|
return p.error('wrong pub keyword usage')
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -591,8 +590,7 @@ pub fn (mut p Parser) top_stmt() ast.Stmt {
|
||||||
} else if p.pref.is_fmt {
|
} else if p.pref.is_fmt {
|
||||||
return p.stmt(false)
|
return p.stmt(false)
|
||||||
} else {
|
} else {
|
||||||
p.error('bad top level statement ' + p.tok.str())
|
return p.error('bad top level statement ' + p.tok.str())
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -720,12 +718,10 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
|
||||||
pos: spos.extend(p.tok.position())
|
pos: spos.extend(p.tok.position())
|
||||||
}
|
}
|
||||||
} else if p.peek_tok.kind == .name {
|
} else if p.peek_tok.kind == .name {
|
||||||
p.error_with_pos('unexpected name `$p.peek_tok.lit`', p.peek_tok.position())
|
return p.error_with_pos('unexpected name `$p.peek_tok.lit`', p.peek_tok.position())
|
||||||
return ast.Stmt{}
|
|
||||||
} else if !p.inside_if_expr && !p.inside_match_body && !p.inside_or_expr
|
} else if !p.inside_if_expr && !p.inside_match_body && !p.inside_or_expr
|
||||||
&& p.peek_tok.kind in [.rcbr, .eof] && !p.mark_var_as_used(p.tok.lit) {
|
&& p.peek_tok.kind in [.rcbr, .eof] && !p.mark_var_as_used(p.tok.lit) {
|
||||||
p.error_with_pos('`$p.tok.lit` evaluated but not used', p.tok.position())
|
return p.error_with_pos('`$p.tok.lit` evaluated but not used', p.tok.position())
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
return p.parse_multi_expr(is_top_level)
|
return p.parse_multi_expr(is_top_level)
|
||||||
}
|
}
|
||||||
|
@ -759,8 +755,7 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p.error_with_pos('unexpected \$', p.tok.position())
|
return p.error_with_pos('unexpected \$', p.tok.position())
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -820,9 +815,8 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.key_const {
|
.key_const {
|
||||||
p.error_with_pos('const can only be defined at the top level (outside of functions)',
|
return p.error_with_pos('const can only be defined at the top level (outside of functions)',
|
||||||
p.tok.position())
|
p.tok.position())
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
.key_asm {
|
.key_asm {
|
||||||
return p.asm_stmt(false)
|
return p.asm_stmt(false)
|
||||||
|
@ -1483,8 +1477,8 @@ pub fn (mut p Parser) check_for_impure_v(language table.Language, pos token.Posi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut p Parser) error(s string) {
|
pub fn (mut p Parser) error(s string) ast.NodeError {
|
||||||
p.error_with_pos(s, p.tok.position())
|
return p.error_with_pos(s, p.tok.position())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut p Parser) warn(s string) {
|
pub fn (mut p Parser) warn(s string) {
|
||||||
|
@ -1495,7 +1489,7 @@ pub fn (mut p Parser) note(s string) {
|
||||||
p.note_with_pos(s, p.tok.position())
|
p.note_with_pos(s, p.tok.position())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut p Parser) error_with_pos(s string, pos token.Position) {
|
pub fn (mut p Parser) error_with_pos(s string, pos token.Position) ast.NodeError {
|
||||||
if p.pref.fatal_errors {
|
if p.pref.fatal_errors {
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
@ -1523,6 +1517,10 @@ pub fn (mut p Parser) error_with_pos(s string, pos token.Position) {
|
||||||
// The p.next() here is needed, so the parser is more robust, and *always* advances, even in the -silent mode.
|
// The p.next() here is needed, so the parser is more robust, and *always* advances, even in the -silent mode.
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
|
return ast.NodeError{
|
||||||
|
idx: p.errors.len - 1
|
||||||
|
pos: pos
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut p Parser) error_with_error(error errors.Error) {
|
pub fn (mut p Parser) error_with_error(error errors.Error) {
|
||||||
|
@ -1611,8 +1609,7 @@ fn (mut p Parser) parse_multi_expr(is_top_level bool) ast.Stmt {
|
||||||
left, left_comments := p.expr_list()
|
left, left_comments := p.expr_list()
|
||||||
left0 := left[0]
|
left0 := left[0]
|
||||||
if tok.kind == .key_mut && p.tok.kind != .decl_assign {
|
if tok.kind == .key_mut && p.tok.kind != .decl_assign {
|
||||||
p.error('expecting `:=` (e.g. `mut x :=`)')
|
return p.error('expecting `:=` (e.g. `mut x :=`)')
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
// TODO remove translated
|
// TODO remove translated
|
||||||
if p.tok.kind in [.assign, .decl_assign] || p.tok.kind.is_assign() {
|
if p.tok.kind in [.assign, .decl_assign] || p.tok.kind.is_assign() {
|
||||||
|
@ -1624,8 +1621,7 @@ fn (mut p Parser) parse_multi_expr(is_top_level bool) ast.Stmt {
|
||||||
&& node !is ast.PostfixExpr && !(node is ast.InfixExpr
|
&& node !is ast.PostfixExpr && !(node is ast.InfixExpr
|
||||||
&& (node as ast.InfixExpr).op in [.left_shift, .arrow]) && node !is ast.ComptimeCall
|
&& (node as ast.InfixExpr).op in [.left_shift, .arrow]) && node !is ast.ComptimeCall
|
||||||
&& node !is ast.SelectorExpr && node !is ast.DumpExpr {
|
&& node !is ast.SelectorExpr && node !is ast.DumpExpr {
|
||||||
p.error_with_pos('expression evaluated but not used', node.position())
|
return p.error_with_pos('expression evaluated but not used', node.position())
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1819,12 +1815,10 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
cap_expr = p.expr(0)
|
cap_expr = p.expr(0)
|
||||||
}
|
}
|
||||||
'len', 'init' {
|
'len', 'init' {
|
||||||
p.error('`$key` cannot be initialized for `chan`. Did you mean `cap`?')
|
return p.error('`$key` cannot be initialized for `chan`. Did you mean `cap`?')
|
||||||
return ast.Expr{}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p.error('wrong field `$key`, expecting `cap`')
|
return p.error('wrong field `$key`, expecting `cap`')
|
||||||
return ast.Expr{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
last_pos = p.tok.position()
|
last_pos = p.tok.position()
|
||||||
|
@ -1843,15 +1837,13 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
||||||
return p.string_expr()
|
return p.string_expr()
|
||||||
} else {
|
} else {
|
||||||
// don't allow any other string prefix except `r`, `js` and `c`
|
// don't allow any other string prefix except `r`, `js` and `c`
|
||||||
p.error('only `c`, `r`, `js` are recognized string prefixes, but you tried to use `$p.tok.lit`')
|
return p.error('only `c`, `r`, `js` are recognized string prefixes, but you tried to use `$p.tok.lit`')
|
||||||
return ast.Expr{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// don't allow r`byte` and c`byte`
|
// don't allow r`byte` and c`byte`
|
||||||
if p.tok.lit in ['r', 'c'] && p.peek_tok.kind == .chartoken {
|
if p.tok.lit in ['r', 'c'] && p.peek_tok.kind == .chartoken {
|
||||||
opt := if p.tok.lit == 'r' { '`r` (raw string)' } else { '`c` (c string)' }
|
opt := if p.tok.lit == 'r' { '`r` (raw string)' } else { '`c` (c string)' }
|
||||||
p.error('cannot use $opt with `byte` and `rune`')
|
return p.error('cannot use $opt with `byte` and `rune`')
|
||||||
return ast.Expr{}
|
|
||||||
}
|
}
|
||||||
known_var := p.mark_var_as_used(p.tok.lit)
|
known_var := p.mark_var_as_used(p.tok.lit)
|
||||||
mut is_mod_cast := false
|
mut is_mod_cast := false
|
||||||
|
@ -2342,8 +2334,7 @@ fn (mut p Parser) string_expr() ast.Expr {
|
||||||
has_fmt = true
|
has_fmt = true
|
||||||
p.next()
|
p.next()
|
||||||
} else {
|
} else {
|
||||||
p.error('format specifier may only be one letter')
|
return p.error('format specifier may only be one letter')
|
||||||
return ast.Expr{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3072,13 +3063,11 @@ fn (mut p Parser) unsafe_stmt() ast.Stmt {
|
||||||
mut pos := p.tok.position()
|
mut pos := p.tok.position()
|
||||||
p.next()
|
p.next()
|
||||||
if p.tok.kind != .lcbr {
|
if p.tok.kind != .lcbr {
|
||||||
p.error_with_pos('please use `unsafe {`', p.tok.position())
|
return p.error_with_pos('please use `unsafe {`', p.tok.position())
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
p.next()
|
p.next()
|
||||||
if p.inside_unsafe {
|
if p.inside_unsafe {
|
||||||
p.error_with_pos('already inside `unsafe` block', pos)
|
return p.error_with_pos('already inside `unsafe` block', pos)
|
||||||
return ast.Stmt{}
|
|
||||||
}
|
}
|
||||||
if p.tok.kind == .rcbr {
|
if p.tok.kind == .rcbr {
|
||||||
// `unsafe {}`
|
// `unsafe {}`
|
||||||
|
|
|
@ -69,8 +69,7 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||||
return p.if_expr(true)
|
return p.if_expr(true)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p.error_with_pos('unexpected `$`', p.peek_tok.position())
|
return p.error_with_pos('unexpected `$`', p.peek_tok.position())
|
||||||
return ast.Expr{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,8 +134,7 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||||
mut pos := p.tok.position()
|
mut pos := p.tok.position()
|
||||||
p.next()
|
p.next()
|
||||||
if p.inside_unsafe {
|
if p.inside_unsafe {
|
||||||
p.error_with_pos('already inside `unsafe` block', pos)
|
return p.error_with_pos('already inside `unsafe` block', pos)
|
||||||
return ast.Expr{}
|
|
||||||
}
|
}
|
||||||
p.inside_unsafe = true
|
p.inside_unsafe = true
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
|
@ -240,8 +238,8 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||||
st := p.parse_type()
|
st := p.parse_type()
|
||||||
p.check(.comma)
|
p.check(.comma)
|
||||||
if p.tok.kind != .name {
|
if p.tok.kind != .name {
|
||||||
p.error_with_pos('unexpected `$p.tok.lit`, expecting struct field', p.tok.position())
|
return p.error_with_pos('unexpected `$p.tok.lit`, expecting struct field',
|
||||||
return ast.Expr{}
|
p.tok.position())
|
||||||
}
|
}
|
||||||
field := p.tok.lit
|
field := p.tok.lit
|
||||||
p.next()
|
p.next()
|
||||||
|
@ -281,13 +279,11 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||||
node = p.struct_init(true) // short_syntax: true
|
node = p.struct_init(true) // short_syntax: true
|
||||||
} else if p.tok.kind == .name {
|
} else if p.tok.kind == .name {
|
||||||
p.next()
|
p.next()
|
||||||
p.error_with_pos('unexpected $p.tok, expecting `:` after struct field name',
|
return p.error_with_pos('unexpected $p.tok, expecting `:` after struct field name',
|
||||||
p.tok.position())
|
p.tok.position())
|
||||||
return ast.Expr{}
|
|
||||||
} else {
|
} else {
|
||||||
p.error_with_pos('unexpected $p.tok, expecting struct field name',
|
return p.error_with_pos('unexpected $p.tok, expecting struct field name',
|
||||||
p.tok.position())
|
p.tok.position())
|
||||||
return ast.Expr{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.check(.rcbr)
|
p.check(.rcbr)
|
||||||
|
@ -326,8 +322,7 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||||
else {
|
else {
|
||||||
if p.tok.kind != .eof && !(p.tok.kind == .rsbr && p.inside_asm) {
|
if p.tok.kind != .eof && !(p.tok.kind == .rsbr && p.inside_asm) {
|
||||||
// eof should be handled where it happens
|
// eof should be handled where it happens
|
||||||
p.error_with_pos('invalid expression: unexpected $p.tok', p.tok.position())
|
return p.error_with_pos('invalid expression: unexpected $p.tok', p.tok.position())
|
||||||
return ast.Expr{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,8 +52,7 @@ fn (mut p Parser) sql_expr() ast.Expr {
|
||||||
if p.tok.kind == .name && p.tok.lit == 'by' {
|
if p.tok.kind == .name && p.tok.lit == 'by' {
|
||||||
p.check_name() // `by`
|
p.check_name() // `by`
|
||||||
} else {
|
} else {
|
||||||
p.error_with_pos('use `order by` in ORM queries', order_pos)
|
return p.error_with_pos('use `order by` in ORM queries', order_pos)
|
||||||
return ast.Expr{}
|
|
||||||
}
|
}
|
||||||
has_order = true
|
has_order = true
|
||||||
order_expr = p.expr(0)
|
order_expr = p.expr(0)
|
||||||
|
|
Loading…
Reference in New Issue