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{
is_c: '-c' in args
is_l: '-l' in args
is_w: '-w' in args
is_w: '-ww' in args
is_diff: '-diff' in args
is_verbose: '-verbose' in args || '--verbose' in args
is_all: '-all' in args || '--all' in args

View File

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

View File

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

View File

@ -391,6 +391,10 @@ fn (mut v Builder) cc() {
linker_flags << '-lm'
}
args := a.join(' ') + ' ' + linker_flags.join(' ')
if v.pref.is_verbose {
println('cc args=$args')
println(a)
}
start:
todo()
// 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'
sysroot := os.home_dir() + '.vmodules/linuxroot/'
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'
if c.pref.show_cc {
mut cc_args := '-fPIC -w -c -target x86_64-linux-gnu -c -o x.o $b.out_name_c -I $sysroot/include '
cflags := b.get_os_cflags()
cc_args += cflags.c_options_without_object_files()
if b.pref.show_cc {
println('cc $cc_args')
}
if os.system('cc $cc_args') != 0 {
println('Cross compilation for Linux failed. Make sure you have clang installed.')
cc_res := os.exec('cc $cc_args') or { return }
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 := [
'-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'
'$sysroot/crt1.o $sysroot/crti.o x.o'
//'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
//s = s.replace('SYSROOT', sysroot) // TODO $ inter bug
//s = s.replace('-o hi', '-o ' + c.pref.out_name)
if c.pref.show_cc {
if b.pref.show_cc {
println(cmd)
}
res := os.exec(cmd) or { return }
//println('output:')
//println(x.output)
if res.exit_code != 0 {
println('Cross compilation for Linux failed. Make sure you have clang installed.')
return
println('Cross compilation for Linux failed (second step, lld):')
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() {

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)
}
}
/*
// TODO not a Stmt
ast.ConstField {
if stmt.is_pub {
c.warn('const field `$stmt.name` $no_pub_in_main_warning', stmt.pos)
}
}
*/
ast.EnumDecl {
if stmt.is_pub {
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
}
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))
field_name := selector_expr.field_name
// variadic
@ -1795,6 +1797,9 @@ fn (mut c Checker) stmt(node ast.Stmt) {
c.return_stmt(mut it)
c.scope_returns = true
}
ast.SqlInsertExpr {
c.sql_insert_expr(node)
}
ast.StructDecl {
c.struct_decl(it)
}
@ -1932,7 +1937,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
if node.is_vweb {
// TODO assoc parser bug
pref := *c.pref
pref2 := {pref|is_vweb: true}
pref2 := {pref|is_vweb: true}
mut c2 := new_checker(c.table, pref2)
c2.check(node.vweb_tmpl)
c.warnings << c2.warnings
@ -2023,9 +2028,6 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
ast.SqlExpr {
return c.sql_expr(node)
}
ast.SqlInsertExpr {
return c.sql_insert_expr(node)
}
ast.StringLiteral {
if node.language == .c {
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 {
ok := if cond_type_sym.kind == .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 {
// interface match
c.type_implements(typ, cond_type, node.pos)
}
if !ok {
@ -2625,10 +2630,12 @@ fn (mut c Checker) sql_expr(node ast.SqlExpr) table.Type {
if node.has_where {
c.expr(node.where_expr)
}
c.expr(node.db_expr)
return node.typ
}
fn (mut c Checker) sql_insert_expr(node ast.SqlInsertExpr) table.Type {
c.expr(node.db_expr)
return table.void_type
}

View File

@ -601,9 +601,6 @@ fn (mut g JsGen) expr(node ast.Expr) {
ast.SqlExpr{
// TODO
}
ast.SqlInsertExpr{
// TODO
}
ast.StringInterLiteral {
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')
db_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 ('
for i, field in fields {
if field.name == 'id' {
@ -95,7 +97,9 @@ fn (mut g Gen) sql_select_expr(node ast.SqlExpr) {
db_name := g.new_tmp_var()
g.writeln('\n\t// sql select')
// 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($db_name, tos_lit("$q')
if node.has_where && node.where_expr is ast.InfixExpr {

View File

@ -10,8 +10,9 @@ import v.vmod
import v.table
import vweb.tmpl
// #flag darwin -I.
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']
supported_ccompilers = ['tinyc', 'clang', 'mingw', 'msvc', 'gcc']
)
@ -21,7 +22,7 @@ fn (mut p Parser) resolve_vroot(flag string) string {
vmod_file_location := mcache.get_by_folder(p.file_name_dir)
if vmod_file_location.vmod_file.len == 0 {
// 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.')
}
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'] {
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"')
@ -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)
if p.pref.is_verbose {
println('\n\n')
println('>>> vweb template for ${path}:')
println('>>> vweb template for $path:')
println(v_code)
println('>>> end of vweb template END')
println('\n\n')
@ -156,20 +157,20 @@ fn (mut p Parser) comp_if() ast.Stmt {
val := p.check_name()
mut stmts := []ast.Stmt{}
mut skip := false
if val in supported_platforms {
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
}
} else if val in supported_ccompilers {
cc := cc_from_string(val)
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
}
}
// `$if os {` or `$if compiler {` for a different target, skip everything inside
// to avoid compilation errors (like including <windows.h> or calling WinAPI fns
// on non-Windows systems)
@ -196,8 +197,9 @@ fn (mut p Parser) comp_if() ast.Stmt {
}
p.next()
}
} else { skip = false }
} else {
skip = false
}
mut is_opt := false
if p.tok.kind == .question {
p.next()
@ -213,7 +215,8 @@ fn (mut p Parser) comp_if() ast.Stmt {
val: val
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()
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
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('.')
if 'tcc' in cc { return .tinyc }
if 'tinyc' in cc { return .tinyc }
if 'clang' in cc { return .clang }
if 'mingw' in cc { return .mingw }
if 'msvc' in cc { return .msvc }
if 'tcc' in cc {
return .tinyc
}
if 'tinyc' in cc {
return .tinyc
}
if 'clang' in cc {
return .clang
}
if 'mingw' in cc {
return .mingw
}
if 'msvc' in cc {
return .msvc
}
return .gcc
}

View File

@ -161,7 +161,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
p.parse_type()
}
is_sum_type = true
} else {
// Expression match
for {
@ -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
}
p.check(.rcbr)
//return ast.StructInit{}
return ast.MatchExpr{
branches: branches
cond: cond

View File

@ -333,7 +333,11 @@ fn (mut p Parser) check(expected token.Kind) {
// p.next()
// }
if p.tok.kind != expected {
p.error('unexpected `$p.tok.kind.str()`, expecting `$expected.str()`')
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.next()
}
@ -907,7 +911,7 @@ pub fn (mut p Parser) name_expr() ast.Expr {
node = p.call_expr(language, mod)
}
} 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
} else if p.peek_tok.kind == .dot && (p.tok.lit[0].is_capital() && !known_var && language ==
.v) {

View File

@ -21,7 +21,9 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
}
.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()
p.inside_match = false
} else {
node = p.name_expr()
p.is_stmt_ident = is_stmt_ident

View File

@ -9,7 +9,7 @@ import v.table
fn (mut p Parser) sql_expr() ast.Expr {
// `sql db {`
p.check_name()
db_var_name := p.check_name()
db_expr := p.expr(0)
p.check(.lcbr)
// kind := ast.SqlExprKind.select_
//
@ -31,7 +31,8 @@ fn (mut p Parser) sql_expr() ast.Expr {
sym := p.table.get_type_symbol(table_type)
table_name := sym.name
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
if has_where {
p.next()
@ -63,19 +64,7 @@ fn (mut p Parser) sql_expr() ast.Expr {
// get only string and int fields
// mut fields := []Var
info := sym.info as table.Struct
fields := info.fields.filter(it.typ in [table.string_type, table.int_type, table.bool_type])
/*
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
}
*/
fields := info.fields.filter(it.typ in [table.string_type, table.int_type, table.bool_type] && 'skip' !in it.attrs)
if fields.len == 0 {
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{
is_count: is_count
typ: typ
db_var_name: db_var_name
db_expr: db_expr
table_name: table_name
where_expr: where_expr
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 {
p.inside_match = true
defer { p.inside_match = false }
// `sql db {`
p.check_name()
db_var_name := p.check_name()
db_expr := p.expr(0)
//println(typeof(db_expr))
p.check(.lcbr)
// kind := ast.SqlExprKind.select_
//
@ -130,7 +122,7 @@ fn (mut p Parser) sql_insert_expr() ast.SqlInsertExpr {
table_name := sym.name
p.check(.rcbr)
return ast.SqlInsertExpr{
db_var_name: db_var_name
db_expr: db_expr
table_name: table_name
table_type: table_type
object_var_name: object_var_name