checker: check sum types in `match`; cross compilation fixes; orm fixes

pull/5451/head
Alexander Medvednikov 2020-06-21 23:09:17 +02:00
parent 9c6b772395
commit 011e26ca9a
12 changed files with 116 additions and 81 deletions

View File

@ -44,7 +44,7 @@ fn main() {
foptions := FormatOptions{ foptions := FormatOptions{
is_c: '-c' in args is_c: '-c' in args
is_l: '-l' in args is_l: '-l' in args
is_w: '-w' in args is_w: '-ww' in args
is_diff: '-diff' in args is_diff: '-diff' in args
is_verbose: '-verbose' in args || '--verbose' in args is_verbose: '-verbose' in args || '--verbose' in args
is_all: '-all' in args || '--all' in args is_all: '-all' in args || '--all' in args

View File

@ -3,6 +3,10 @@ module sqlite
#flag -lsqlite3 #flag -lsqlite3
#flag freebsd -I/usr/local/include #flag freebsd -I/usr/local/include
#flag freebsd -Wl -L/usr/local/lib -lsqlite3 #flag freebsd -Wl -L/usr/local/lib -lsqlite3
//#flag linux -I @VROOT/thirdparty/sqlite
//#flag @VROOT/thirdparty/sqlite/sqlite.c
#include "sqlite3.h" #include "sqlite3.h"
struct C.sqlite3 {} struct C.sqlite3 {}

View File

@ -9,16 +9,16 @@ import v.errors
pub type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl pub type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl
pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | BoolLiteral | CallExpr | CastExpr | CharLiteral | pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | BoolLiteral | CallExpr | CastExpr |
ComptimeCall | ConcatExpr | EnumVal | FloatLiteral | Ident | IfExpr | IfGuardExpr | IndexExpr | CharLiteral | ComptimeCall | ConcatExpr | EnumVal | FloatLiteral | Ident | IfExpr | IfGuardExpr |
InfixExpr | IntegerLiteral | Likely | MapInit | MatchExpr | None | OrExpr | ParExpr | PostfixExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | MapInit | MatchExpr | None | OrExpr |
PrefixExpr | RangeExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral | StringLiteral | ParExpr | PostfixExpr | PrefixExpr | RangeExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral |
StructInit | Type | TypeOf StringLiteral | StructInit | Type | TypeOf
pub type Stmt = AssertStmt | AssignStmt | Attr | Block | BranchStmt | Comment | CompIf | ConstDecl | pub type Stmt = AssertStmt | AssignStmt | Attr | Block | BranchStmt | Comment | CompIf |
DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl | GoStmt | ConstDecl | DeferStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt |
GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module | Return | SqlInsertExpr | GlobalDecl | GoStmt | GotoLabel | GotoStmt | HashStmt | Import | InterfaceDecl | Module |
StructDecl | TypeDecl | UnsafeStmt Return | SqlInsertExpr | StructDecl | TypeDecl | UnsafeStmt
pub type ScopeObject = ConstField | GlobalDecl | Var pub type ScopeObject = ConstField | GlobalDecl | Var
@ -809,7 +809,7 @@ pub enum SqlExprKind {
*/ */
pub struct SqlInsertExpr { pub struct SqlInsertExpr {
pub: pub:
db_var_name string // `db` in `sql db {` db_expr Expr // `db` in `sql db {`
table_name string table_name string
object_var_name string // `user` object_var_name string // `user`
table_type table.Type table_type table.Type
@ -819,7 +819,7 @@ pub struct SqlExpr {
pub: pub:
typ table.Type typ table.Type
is_count bool is_count bool
db_var_name string // `db` in `sql db {` db_expr Expr // `db` in `sql db {`
table_name string table_name string
where_expr Expr where_expr Expr
has_where bool has_where bool
@ -879,7 +879,8 @@ pub fn (expr Expr) position() token.Position {
InfixExpr { InfixExpr {
left_pos := expr.left.position() left_pos := expr.left.position()
right_pos := expr.right.position() right_pos := expr.right.position()
if left_pos.pos == 0 || right_pos.pos == 0 { if left_pos.pos == 0 ||
right_pos.pos == 0 {
return expr.pos return expr.pos
} }
return token.Position{ return token.Position{

View File

@ -391,6 +391,10 @@ fn (mut v Builder) cc() {
linker_flags << '-lm' linker_flags << '-lm'
} }
args := a.join(' ') + ' ' + linker_flags.join(' ') args := a.join(' ') + ' ' + linker_flags.join(' ')
if v.pref.is_verbose {
println('cc args=$args')
println(a)
}
start: start:
todo() todo()
// TODO remove // TODO remove
@ -512,7 +516,7 @@ fn (mut v Builder) cc() {
} }
} }
fn (mut c Builder) cc_linux_cross() { fn (mut b Builder) cc_linux_cross() {
parent_dir := os.home_dir() + '.vmodules' parent_dir := os.home_dir() + '.vmodules'
sysroot := os.home_dir() + '.vmodules/linuxroot/' sysroot := os.home_dir() + '.vmodules/linuxroot/'
if !os.is_dir(sysroot) { if !os.is_dir(sysroot) {
@ -526,17 +530,22 @@ fn (mut c Builder) cc_linux_cross() {
} }
} }
mut cc_args := '-fPIC -w -c -target x86_64-linux-gnu -c -o x.o $c.out_name_c -I $sysroot/include' mut cc_args := '-fPIC -w -c -target x86_64-linux-gnu -c -o x.o $b.out_name_c -I $sysroot/include '
if c.pref.show_cc { cflags := b.get_os_cflags()
cc_args += cflags.c_options_without_object_files()
if b.pref.show_cc {
println('cc $cc_args') println('cc $cc_args')
} }
if os.system('cc $cc_args') != 0 { cc_res := os.exec('cc $cc_args') or { return }
println('Cross compilation for Linux failed. Make sure you have clang installed.') if cc_res.exit_code != 0 {
println('Cross compilation for Linux failed (first step, clang). Make sure you have clang installed.')
println(cc_res.output)
exit(1)
} }
linker_args := [ linker_args := [
'-L $sysroot/usr/lib/x86_64-linux-gnu/' '-L $sysroot/usr/lib/x86_64-linux-gnu/'
'--sysroot=$sysroot -v -o $c.pref.out_name -m elf_x86_64' '--sysroot=$sysroot -v -o $b.pref.out_name -m elf_x86_64'
'-dynamic-linker /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2' '-dynamic-linker /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2'
'$sysroot/crt1.o $sysroot/crti.o x.o' '$sysroot/crt1.o $sysroot/crti.o x.o'
//'SYSROOT/lib/x86_64-linux-gnu/libc.so.6' //'SYSROOT/lib/x86_64-linux-gnu/libc.so.6'
@ -554,17 +563,16 @@ fn (mut c Builder) cc_linux_cross() {
cmd := '$sysroot/ld.lld ' + linker_args_str cmd := '$sysroot/ld.lld ' + linker_args_str
//s = s.replace('SYSROOT', sysroot) // TODO $ inter bug //s = s.replace('SYSROOT', sysroot) // TODO $ inter bug
//s = s.replace('-o hi', '-o ' + c.pref.out_name) //s = s.replace('-o hi', '-o ' + c.pref.out_name)
if c.pref.show_cc { if b.pref.show_cc {
println(cmd) println(cmd)
} }
res := os.exec(cmd) or { return } res := os.exec(cmd) or { return }
//println('output:')
//println(x.output)
if res.exit_code != 0 { if res.exit_code != 0 {
println('Cross compilation for Linux failed. Make sure you have clang installed.') println('Cross compilation for Linux failed (second step, lld):')
return println(res.output)
exit(1)
} }
println(c.pref.out_name + ' has been successfully compiled') println(b.pref.out_name + ' has been successfully compiled')
} }
fn (mut c Builder) cc_windows_cross() { fn (mut c Builder) cc_windows_cross() {

View File

@ -143,11 +143,14 @@ fn (mut c Checker) check_file_in_main(file ast.File) bool {
c.warn('const $no_pub_in_main_warning', stmt.pos) c.warn('const $no_pub_in_main_warning', stmt.pos)
} }
} }
/*
// TODO not a Stmt
ast.ConstField { ast.ConstField {
if stmt.is_pub { if stmt.is_pub {
c.warn('const field `$stmt.name` $no_pub_in_main_warning', stmt.pos) c.warn('const field `$stmt.name` $no_pub_in_main_warning', stmt.pos)
} }
} }
*/
ast.EnumDecl { ast.EnumDecl {
if stmt.is_pub { if stmt.is_pub {
c.warn('enum `$stmt.name` $no_pub_in_main_warning', stmt.pos) c.warn('enum `$stmt.name` $no_pub_in_main_warning', stmt.pos)
@ -1206,7 +1209,6 @@ pub fn (mut c Checker) selector_expr(mut selector_expr ast.SelectorExpr) table.T
return table.void_type return table.void_type
} }
selector_expr.expr_type = typ selector_expr.expr_type = typ
// println('sel expr line_nr=$selector_expr.pos.line_nr typ=$selector_expr.expr_type')
sym := c.table.get_type_symbol(c.unwrap_generic(typ)) sym := c.table.get_type_symbol(c.unwrap_generic(typ))
field_name := selector_expr.field_name field_name := selector_expr.field_name
// variadic // variadic
@ -1795,6 +1797,9 @@ fn (mut c Checker) stmt(node ast.Stmt) {
c.return_stmt(mut it) c.return_stmt(mut it)
c.scope_returns = true c.scope_returns = true
} }
ast.SqlInsertExpr {
c.sql_insert_expr(node)
}
ast.StructDecl { ast.StructDecl {
c.struct_decl(it) c.struct_decl(it)
} }
@ -2023,9 +2028,6 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
ast.SqlExpr { ast.SqlExpr {
return c.sql_expr(node) return c.sql_expr(node)
} }
ast.SqlInsertExpr {
return c.sql_insert_expr(node)
}
ast.StringLiteral { ast.StringLiteral {
if node.language == .c { if node.language == .c {
return table.byteptr_type return table.byteptr_type
@ -2225,8 +2227,11 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) table.Type {
if node.is_sum_type || node.is_interface { if node.is_sum_type || node.is_interface {
ok := if cond_type_sym.kind == .sum_type { ok := if cond_type_sym.kind == .sum_type {
// TODO verify sum type // TODO verify sum type
true // c.check_types(typ, cond_type) //true // c.check_types(typ, cond_type)
info := cond_type_sym.info as table.SumType
typ in info.variants
} else { } else {
// interface match
c.type_implements(typ, cond_type, node.pos) c.type_implements(typ, cond_type, node.pos)
} }
if !ok { if !ok {
@ -2625,10 +2630,12 @@ fn (mut c Checker) sql_expr(node ast.SqlExpr) table.Type {
if node.has_where { if node.has_where {
c.expr(node.where_expr) c.expr(node.where_expr)
} }
c.expr(node.db_expr)
return node.typ return node.typ
} }
fn (mut c Checker) sql_insert_expr(node ast.SqlInsertExpr) table.Type { fn (mut c Checker) sql_insert_expr(node ast.SqlInsertExpr) table.Type {
c.expr(node.db_expr)
return table.void_type return table.void_type
} }

View File

@ -601,9 +601,6 @@ fn (mut g JsGen) expr(node ast.Expr) {
ast.SqlExpr{ ast.SqlExpr{
// TODO // TODO
} }
ast.SqlInsertExpr{
// TODO
}
ast.StringInterLiteral { ast.StringInterLiteral {
g.gen_string_inter_literal(it) g.gen_string_inter_literal(it)
} }

View File

@ -20,7 +20,9 @@ fn (mut g Gen) sql_insert_expr(node ast.SqlInsertExpr) {
g.writeln('\n\t// sql insert') g.writeln('\n\t// sql insert')
db_name := g.new_tmp_var() db_name := g.new_tmp_var()
g.sql_stmt_name = g.new_tmp_var() g.sql_stmt_name = g.new_tmp_var()
g.writeln('${dbtype}__DB $db_name = $node.db_var_name;') g.write('${dbtype}__DB $db_name = ')
g.expr(node.db_expr)
g.writeln(';')
mut q := 'insert into $node.table_name (' mut q := 'insert into $node.table_name ('
for i, field in fields { for i, field in fields {
if field.name == 'id' { if field.name == 'id' {
@ -95,7 +97,9 @@ fn (mut g Gen) sql_select_expr(node ast.SqlExpr) {
db_name := g.new_tmp_var() db_name := g.new_tmp_var()
g.writeln('\n\t// sql select') g.writeln('\n\t// sql select')
// g.write('${dbtype}__DB $db_name = *(${dbtype}__DB*)${node.db_var_name}.data;') // g.write('${dbtype}__DB $db_name = *(${dbtype}__DB*)${node.db_var_name}.data;')
g.writeln('${dbtype}__DB $db_name = $node.db_var_name;') g.write('${dbtype}__DB $db_name = ') // $node.db_var_name;')
g.expr(node.db_expr)
g.writeln(';')
// g.write('sqlite3_stmt* $g.sql_stmt_name = ${dbtype}__DB_init_stmt(*(${dbtype}__DB*)${node.db_var_name}.data, tos_lit("$q') // g.write('sqlite3_stmt* $g.sql_stmt_name = ${dbtype}__DB_init_stmt(*(${dbtype}__DB*)${node.db_var_name}.data, tos_lit("$q')
g.write('sqlite3_stmt* $g.sql_stmt_name = ${dbtype}__DB_init_stmt($db_name, tos_lit("$q') g.write('sqlite3_stmt* $g.sql_stmt_name = ${dbtype}__DB_init_stmt($db_name, tos_lit("$q')
if node.has_where && node.where_expr is ast.InfixExpr { if node.has_where && node.where_expr is ast.InfixExpr {

View File

@ -10,6 +10,7 @@ import v.vmod
import v.table import v.table
import vweb.tmpl import vweb.tmpl
// #flag darwin -I.
const ( const (
supported_platforms = ['windows', 'mac', 'macos', 'darwin', 'linux', 'freebsd', 'openbsd', supported_platforms = ['windows', 'mac', 'macos', 'darwin', 'linux', 'freebsd', 'openbsd',
'netbsd', 'dragonfly', 'android', 'js', 'solaris', 'haiku', 'linux_or_macos'] 'netbsd', 'dragonfly', 'android', 'js', 'solaris', 'haiku', 'linux_or_macos']
@ -21,7 +22,7 @@ fn (mut p Parser) resolve_vroot(flag string) string {
vmod_file_location := mcache.get_by_folder(p.file_name_dir) vmod_file_location := mcache.get_by_folder(p.file_name_dir)
if vmod_file_location.vmod_file.len == 0 { if vmod_file_location.vmod_file.len == 0 {
// There was no actual v.mod file found. // There was no actual v.mod file found.
p.error('To use @VROOT, you need' + ' to have a "v.mod" file in ${p.file_name_dir},' + p.error('To use @VROOT, you need' + ' to have a "v.mod" file in $p.file_name_dir,' +
' or in one of its parent folders.') ' or in one of its parent folders.')
} }
vmod_path := vmod_file_location.vmod_folder vmod_path := vmod_file_location.vmod_folder
@ -56,7 +57,7 @@ fn (mut p Parser) hash() ast.HashStmt {
} }
for deprecated in ['@VMOD', '@VMODULE', '@VPATH', '@VLIB_PATH'] { for deprecated in ['@VMOD', '@VMODULE', '@VPATH', '@VLIB_PATH'] {
if flag.contains(deprecated) { if flag.contains(deprecated) {
p.error('${deprecated} had been deprecated, use @VROOT instead.') p.error('$deprecated had been deprecated, use @VROOT instead.')
} }
} }
// println('adding flag "$flag"') // println('adding flag "$flag"')
@ -110,7 +111,7 @@ fn (mut p Parser) vweb() ast.ComptimeCall {
mut file := parse_text(v_code, p.table, p.pref, scope, p.global_scope) mut file := parse_text(v_code, p.table, p.pref, scope, p.global_scope)
if p.pref.is_verbose { if p.pref.is_verbose {
println('\n\n') println('\n\n')
println('>>> vweb template for ${path}:') println('>>> vweb template for $path:')
println(v_code) println(v_code)
println('>>> end of vweb template END') println('>>> end of vweb template END')
println('\n\n') println('\n\n')
@ -156,20 +157,20 @@ fn (mut p Parser) comp_if() ast.Stmt {
val := p.check_name() val := p.check_name()
mut stmts := []ast.Stmt{} mut stmts := []ast.Stmt{}
mut skip := false mut skip := false
if val in supported_platforms { if val in supported_platforms {
os := os_from_string(val) os := os_from_string(val)
if (!is_not && os != p.pref.os) || (is_not && os == p.pref.os) { if (!is_not && os != p.pref.os) ||
(is_not && os == p.pref.os) {
skip = true skip = true
} }
} else if val in supported_ccompilers { } else if val in supported_ccompilers {
cc := cc_from_string(val) cc := cc_from_string(val)
user_cc := cc_from_string(p.pref.ccompiler) user_cc := cc_from_string(p.pref.ccompiler)
if (!is_not && cc != user_cc) || (is_not && cc == user_cc) { if (!is_not && cc != user_cc) ||
(is_not && cc == user_cc) {
skip = true skip = true
} }
} }
// `$if os {` or `$if compiler {` for a different target, skip everything inside // `$if os {` or `$if compiler {` for a different target, skip everything inside
// to avoid compilation errors (like including <windows.h> or calling WinAPI fns // to avoid compilation errors (like including <windows.h> or calling WinAPI fns
// on non-Windows systems) // on non-Windows systems)
@ -196,8 +197,9 @@ fn (mut p Parser) comp_if() ast.Stmt {
} }
p.next() p.next()
} }
} else { skip = false } } else {
skip = false
}
mut is_opt := false mut is_opt := false
if p.tok.kind == .question { if p.tok.kind == .question {
p.next() p.next()
@ -213,7 +215,8 @@ fn (mut p Parser) comp_if() ast.Stmt {
val: val val: val
stmts: stmts stmts: stmts
} }
if p.tok.kind == .dollar && p.peek_tok.kind == .key_else { if p.tok.kind == .dollar &&
p.peek_tok.kind == .key_else {
p.next() p.next()
p.next() p.next()
node.has_else = true node.has_else = true
@ -282,13 +285,25 @@ fn os_from_string(os string) pref.OS {
// Helper function to convert string names to CC enum // Helper function to convert string names to CC enum
pub fn cc_from_string(cc_str string) pref.CompilerType { pub fn cc_from_string(cc_str string) pref.CompilerType {
if cc_str.len == 0 { return .gcc } if cc_str.len == 0 {
return .gcc
}
cc := cc_str.replace('\\', '/').split('/').last().all_before('.') cc := cc_str.replace('\\', '/').split('/').last().all_before('.')
if 'tcc' in cc { return .tinyc } if 'tcc' in cc {
if 'tinyc' in cc { return .tinyc } return .tinyc
if 'clang' in cc { return .clang } }
if 'mingw' in cc { return .mingw } if 'tinyc' in cc {
if 'msvc' in cc { return .msvc } return .tinyc
}
if 'clang' in cc {
return .clang
}
if 'mingw' in cc {
return .mingw
}
if 'msvc' in cc {
return .msvc
}
return .gcc return .gcc
} }

View File

@ -204,6 +204,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
len: match_last_pos.pos - match_first_pos.pos + match_last_pos.len len: match_last_pos.pos - match_first_pos.pos + match_last_pos.len
} }
p.check(.rcbr) p.check(.rcbr)
//return ast.StructInit{}
return ast.MatchExpr{ return ast.MatchExpr{
branches: branches branches: branches
cond: cond cond: cond

View File

@ -333,8 +333,12 @@ fn (mut p Parser) check(expected token.Kind) {
// p.next() // p.next()
// } // }
if p.tok.kind != expected { if p.tok.kind != expected {
if p.tok.kind == .name {
p.error('unexpected name `$p.tok.lit`, expecting `$expected.str()`')
} else {
p.error('unexpected `$p.tok.kind.str()`, expecting `$expected.str()`') p.error('unexpected `$p.tok.kind.str()`, expecting `$expected.str()`')
} }
}
p.next() p.next()
} }
@ -907,7 +911,7 @@ pub fn (mut p Parser) name_expr() ast.Expr {
node = p.call_expr(language, mod) node = p.call_expr(language, mod)
} }
} else if p.peek_tok.kind == .lcbr && !p.inside_match && !p.inside_match_case && !p.inside_if && } else if p.peek_tok.kind == .lcbr && !p.inside_match && !p.inside_match_case && !p.inside_if &&
!p.inside_for { !p.inside_for { // && (p.tok.lit[0].is_capital() || p.builtin_mod) {
return p.struct_init(false) // short_syntax: false return p.struct_init(false) // short_syntax: false
} else if p.peek_tok.kind == .dot && (p.tok.lit[0].is_capital() && !known_var && language == } else if p.peek_tok.kind == .dot && (p.tok.lit[0].is_capital() && !known_var && language ==
.v) { .v) {

View File

@ -21,7 +21,9 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
} }
.name { .name {
if p.tok.lit == 'sql' && p.peek_tok.kind == .name { if p.tok.lit == 'sql' && p.peek_tok.kind == .name {
p.inside_match = true // reuse the same var for perf instead of inside_sql TODO rename
node = p.sql_expr() node = p.sql_expr()
p.inside_match = false
} else { } else {
node = p.name_expr() node = p.name_expr()
p.is_stmt_ident = is_stmt_ident p.is_stmt_ident = is_stmt_ident

View File

@ -9,7 +9,7 @@ import v.table
fn (mut p Parser) sql_expr() ast.Expr { fn (mut p Parser) sql_expr() ast.Expr {
// `sql db {` // `sql db {`
p.check_name() p.check_name()
db_var_name := p.check_name() db_expr := p.expr(0)
p.check(.lcbr) p.check(.lcbr)
// kind := ast.SqlExprKind.select_ // kind := ast.SqlExprKind.select_
// //
@ -31,7 +31,8 @@ fn (mut p Parser) sql_expr() ast.Expr {
sym := p.table.get_type_symbol(table_type) sym := p.table.get_type_symbol(table_type)
table_name := sym.name table_name := sym.name
mut where_expr := ast.Expr{} mut where_expr := ast.Expr{}
has_where := p.tok.kind == .name && p.tok.lit == 'where' has_where := p.tok.kind == .name &&
p.tok.lit == 'where'
mut query_one := false // one object is returned, not an array mut query_one := false // one object is returned, not an array
if has_where { if has_where {
p.next() p.next()
@ -63,19 +64,7 @@ fn (mut p Parser) sql_expr() ast.Expr {
// get only string and int fields // get only string and int fields
// mut fields := []Var // mut fields := []Var
info := sym.info as table.Struct info := sym.info as table.Struct
fields := info.fields.filter(it.typ in [table.string_type, table.int_type, table.bool_type]) fields := info.fields.filter(it.typ in [table.string_type, table.int_type, table.bool_type] && 'skip' !in it.attrs)
/*
for i, field in info.fields {
if !(field.typ in ['string', 'int', 'bool']) {
println('orm: skipping $field.name')
continue
}
if field.attr.contains('skip') {
continue
}
fields << field
}
*/
if fields.len == 0 { if fields.len == 0 {
p.error('V orm: select: empty fields in `$table_name`') p.error('V orm: select: empty fields in `$table_name`')
} }
@ -96,7 +85,7 @@ fn (mut p Parser) sql_expr() ast.Expr {
return ast.SqlExpr{ return ast.SqlExpr{
is_count: is_count is_count: is_count
typ: typ typ: typ
db_var_name: db_var_name db_expr: db_expr
table_name: table_name table_name: table_name
where_expr: where_expr where_expr: where_expr
has_where: has_where has_where: has_where
@ -106,9 +95,12 @@ fn (mut p Parser) sql_expr() ast.Expr {
} }
fn (mut p Parser) sql_insert_expr() ast.SqlInsertExpr { fn (mut p Parser) sql_insert_expr() ast.SqlInsertExpr {
p.inside_match = true
defer { p.inside_match = false }
// `sql db {` // `sql db {`
p.check_name() p.check_name()
db_var_name := p.check_name() db_expr := p.expr(0)
//println(typeof(db_expr))
p.check(.lcbr) p.check(.lcbr)
// kind := ast.SqlExprKind.select_ // kind := ast.SqlExprKind.select_
// //
@ -130,7 +122,7 @@ fn (mut p Parser) sql_insert_expr() ast.SqlInsertExpr {
table_name := sym.name table_name := sym.name
p.check(.rcbr) p.check(.rcbr)
return ast.SqlInsertExpr{ return ast.SqlInsertExpr{
db_var_name: db_var_name db_expr: db_expr
table_name: table_name table_name: table_name
table_type: table_type table_type: table_type
object_var_name: object_var_name object_var_name: object_var_name