v: support dump(expr) (#9160)
parent
747507dd1d
commit
849cde245c
|
@ -204,7 +204,7 @@ fn (mut f MDFile) parse_line(lnumber int, line string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut f MDFile) dump() {
|
fn (mut f MDFile) debug() {
|
||||||
for e in f.examples {
|
for e in f.examples {
|
||||||
eprintln('f.path: $f.path | example: $e')
|
eprintln('f.path: $f.path | example: $e')
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
fn factorial(n u32) u32 {
|
||||||
|
if dump(n <= 1) {
|
||||||
|
return dump(1)
|
||||||
|
}
|
||||||
|
return dump(n * factorial(n - 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println(factorial(5))
|
||||||
|
}
|
|
@ -11,10 +11,10 @@ pub type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl
|
||||||
|
|
||||||
pub type Expr = AnonFn | ArrayDecompose | ArrayInit | AsCast | Assoc | AtExpr | BoolLiteral |
|
pub type Expr = AnonFn | ArrayDecompose | ArrayInit | AsCast | Assoc | AtExpr | BoolLiteral |
|
||||||
CTempVar | CallExpr | CastExpr | ChanInit | CharLiteral | Comment | ComptimeCall |
|
CTempVar | CallExpr | CastExpr | ChanInit | CharLiteral | Comment | ComptimeCall |
|
||||||
ComptimeSelector | ConcatExpr | EnumVal | FloatLiteral | GoExpr | Ident | IfExpr |
|
ComptimeSelector | ConcatExpr | DumpExpr | EnumVal | FloatLiteral | GoExpr | Ident |
|
||||||
IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr | MapInit |
|
IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr |
|
||||||
MatchExpr | None | OffsetOf | OrExpr | ParExpr | PostfixExpr | PrefixExpr | RangeExpr |
|
MapInit | MatchExpr | None | OffsetOf | OrExpr | ParExpr | PostfixExpr | PrefixExpr |
|
||||||
SelectExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral | StringLiteral |
|
RangeExpr | SelectExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral | StringLiteral |
|
||||||
StructInit | Type | TypeOf | UnsafeExpr
|
StructInit | Type | TypeOf | UnsafeExpr
|
||||||
|
|
||||||
pub type Stmt = AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDecl | DeferStmt |
|
pub type Stmt = AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDecl | DeferStmt |
|
||||||
|
@ -1114,6 +1114,15 @@ pub mut:
|
||||||
expr_type table.Type
|
expr_type table.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct DumpExpr {
|
||||||
|
pub:
|
||||||
|
expr Expr
|
||||||
|
pos token.Position
|
||||||
|
pub mut:
|
||||||
|
expr_type table.Type
|
||||||
|
cname string // filled in the checker
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Comment {
|
pub struct Comment {
|
||||||
pub:
|
pub:
|
||||||
text string
|
text string
|
||||||
|
@ -1240,7 +1249,7 @@ pub fn (expr Expr) position() token.Position {
|
||||||
return expr.decl.pos
|
return expr.decl.pos
|
||||||
}
|
}
|
||||||
ArrayDecompose, ArrayInit, AsCast, Assoc, AtExpr, BoolLiteral, CallExpr, CastExpr, ChanInit,
|
ArrayDecompose, ArrayInit, AsCast, Assoc, AtExpr, BoolLiteral, CallExpr, CastExpr, ChanInit,
|
||||||
CharLiteral, ConcatExpr, Comment, ComptimeCall, ComptimeSelector, EnumVal, FloatLiteral,
|
CharLiteral, ConcatExpr, Comment, ComptimeCall, ComptimeSelector, EnumVal, DumpExpr, FloatLiteral,
|
||||||
GoExpr, Ident, IfExpr, IndexExpr, IntegerLiteral, Likely, LockExpr, MapInit, MatchExpr,
|
GoExpr, Ident, IfExpr, IndexExpr, IntegerLiteral, Likely, LockExpr, MapInit, MatchExpr,
|
||||||
None, OffsetOf, OrExpr, ParExpr, PostfixExpr, PrefixExpr, RangeExpr, SelectExpr, SelectorExpr,
|
None, OffsetOf, OrExpr, ParExpr, PostfixExpr, PrefixExpr, RangeExpr, SelectExpr, SelectorExpr,
|
||||||
SizeOf, SqlExpr, StringInterLiteral, StringLiteral, StructInit, Type, TypeOf, UnsafeExpr
|
SizeOf, SqlExpr, StringInterLiteral, StringLiteral, StructInit, Type, TypeOf, UnsafeExpr
|
||||||
|
|
|
@ -3716,6 +3716,17 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||||
ast.ConcatExpr {
|
ast.ConcatExpr {
|
||||||
return c.concat_expr(mut node)
|
return c.concat_expr(mut node)
|
||||||
}
|
}
|
||||||
|
ast.DumpExpr {
|
||||||
|
node.expr_type = c.expr(node.expr)
|
||||||
|
if node.expr_type.idx() == table.void_type_idx {
|
||||||
|
c.error('dump expression can not be void', node.expr.position())
|
||||||
|
return table.void_type
|
||||||
|
}
|
||||||
|
tsym := c.table.get_type_symbol(node.expr_type)
|
||||||
|
c.table.dumps[int(node.expr_type)] = tsym.cname
|
||||||
|
node.cname = tsym.cname
|
||||||
|
return node.expr_type
|
||||||
|
}
|
||||||
ast.EnumVal {
|
ast.EnumVal {
|
||||||
return c.enum_val(mut node)
|
return c.enum_val(mut node)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
vlib/v/checker/tests/dump_of_void_expr.vv:3:6: error: dump expression can not be void
|
||||||
|
1 | fn abc() {}
|
||||||
|
2 |
|
||||||
|
3 | dump(abc())
|
||||||
|
| ~~~~~
|
|
@ -0,0 +1,3 @@
|
||||||
|
fn abc() {}
|
||||||
|
|
||||||
|
dump(abc())
|
|
@ -900,6 +900,11 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
|
||||||
ast.CTempVar {
|
ast.CTempVar {
|
||||||
eprintln('ast.CTempVar of $node.orig.str() should be generated/used only in cgen')
|
eprintln('ast.CTempVar of $node.orig.str() should be generated/used only in cgen')
|
||||||
}
|
}
|
||||||
|
ast.DumpExpr {
|
||||||
|
f.write('dump(')
|
||||||
|
f.expr(node.expr)
|
||||||
|
f.write(')')
|
||||||
|
}
|
||||||
ast.AnonFn {
|
ast.AnonFn {
|
||||||
f.fn_decl(node.decl)
|
f.fn_decl(node.decl)
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,6 +266,8 @@ pub fn gen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
||||||
g.definitions.writeln('int _v_type_idx_${typ.cname}() { return $idx; };')
|
g.definitions.writeln('int _v_type_idx_${typ.cname}() { return $idx; };')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
g.dump_expr_definitions()
|
||||||
// v files are finished, what remains is pure C code
|
// v files are finished, what remains is pure C code
|
||||||
g.gen_vlines_reset()
|
g.gen_vlines_reset()
|
||||||
if g.pref.build_mode != .build_module {
|
if g.pref.build_mode != .build_module {
|
||||||
|
@ -2698,6 +2700,9 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||||
g.write("L'$node.val'")
|
g.write("L'$node.val'")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast.DumpExpr {
|
||||||
|
g.dump_expr(node)
|
||||||
|
}
|
||||||
ast.AtExpr {
|
ast.AtExpr {
|
||||||
g.comp_at(node)
|
g.comp_at(node)
|
||||||
}
|
}
|
||||||
|
@ -2965,7 +2970,9 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
||||||
g.write('(*(')
|
g.write('(*(')
|
||||||
}
|
}
|
||||||
if sym.kind == .array_fixed {
|
if sym.kind == .array_fixed {
|
||||||
assert node.field_name == 'len'
|
if node.field_name != 'len' {
|
||||||
|
g.error('field_name should be `len`', node.pos)
|
||||||
|
}
|
||||||
info := sym.info as table.ArrayFixed
|
info := sym.info as table.ArrayFixed
|
||||||
g.write('$info.size')
|
g.write('$info.size')
|
||||||
return
|
return
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
module c
|
||||||
|
|
||||||
|
import v.ast
|
||||||
|
|
||||||
|
fn (mut g Gen) dump_expr(node ast.DumpExpr) {
|
||||||
|
sexpr := ctoslit(node.expr.str())
|
||||||
|
fpath := cestring(g.file.path)
|
||||||
|
line := node.pos.line_nr + 1
|
||||||
|
if 'nop_dump' in g.pref.compile_defines {
|
||||||
|
g.expr(node.expr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
g.write(' _v_dump_expr_${node.cname}(${ctoslit(fpath)}, $line, $sexpr, ')
|
||||||
|
g.expr(node.expr)
|
||||||
|
g.write(' )')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) dump_expr_definitions() {
|
||||||
|
if g.pref.build_mode == .build_module {
|
||||||
|
for _, cname in g.table.dumps {
|
||||||
|
g.definitions.writeln('$cname _v_dump_expr_${cname}(string fpath, int line, string sexpr, $cname x);')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for dump_type, cname in g.table.dumps {
|
||||||
|
to_string_fn_name := g.gen_str_for_type(dump_type)
|
||||||
|
g.definitions.writeln('$cname _v_dump_expr_${cname}(string fpath, int line, string sexpr, $cname x) {')
|
||||||
|
g.definitions.writeln('\teprint(${ctoslit('[')});')
|
||||||
|
g.definitions.writeln('\teprint(fpath);')
|
||||||
|
g.definitions.writeln('\teprint(${ctoslit(':')});')
|
||||||
|
g.definitions.writeln('\teprint(int_str(line));')
|
||||||
|
g.definitions.writeln('\teprint(${ctoslit('] ')});')
|
||||||
|
g.definitions.writeln('\teprint(sexpr);')
|
||||||
|
g.definitions.writeln('\teprint(${ctoslit(': ')});')
|
||||||
|
g.definitions.writeln('\teprintln(${to_string_fn_name}(x));')
|
||||||
|
g.definitions.writeln('\treturn x;')
|
||||||
|
g.definitions.writeln('}')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,19 +10,19 @@ import v.depgraph
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// https://ecma-international.org/ecma-262/#sec-reserved-words
|
// https://ecma-international.org/ecma-262/#sec-reserved-words
|
||||||
js_reserved = ['await', 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger',
|
js_reserved = ['await', 'break', 'case', 'catch', 'class', 'const', 'continue', 'debugger',
|
||||||
'default', 'delete', 'do', 'else', 'enum', 'export', 'extends', 'finally', 'for', 'function',
|
'default', 'delete', 'do', 'else', 'enum', 'export', 'extends', 'finally', 'for', 'function',
|
||||||
'if', 'implements', 'import', 'in', 'instanceof', 'interface', 'let', 'new', 'package',
|
'if', 'implements', 'import', 'in', 'instanceof', 'interface', 'let', 'new', 'package',
|
||||||
'private', 'protected', 'public', 'return', 'static', 'super', 'switch', 'this', 'throw',
|
'private', 'protected', 'public', 'return', 'static', 'super', 'switch', 'this', 'throw',
|
||||||
'try', 'typeof', 'var', 'void', 'while', 'with', 'yield', 'Number', 'String', 'Boolean',
|
'try', 'typeof', 'var', 'void', 'while', 'with', 'yield', 'Number', 'String', 'Boolean',
|
||||||
'Array', 'Map']
|
'Array', 'Map']
|
||||||
// used to generate type structs
|
// used to generate type structs
|
||||||
v_types = ['i8', 'i16', 'int', 'i64', 'byte', 'u16', 'u32', 'u64', 'f32', 'f64', 'int_literal',
|
v_types = ['i8', 'i16', 'int', 'i64', 'byte', 'u16', 'u32', 'u64', 'f32', 'f64',
|
||||||
'float_literal', 'size_t', 'bool', 'string', 'map', 'array']
|
'int_literal', 'float_literal', 'size_t', 'bool', 'string', 'map', 'array']
|
||||||
shallow_equatables = [table.Kind.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64, .f32, .f64, .int_literal,
|
shallow_equatables = [table.Kind.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64, .f32, .f64,
|
||||||
.float_literal, .size_t, .bool, .string]
|
.int_literal, .float_literal, .size_t, .bool, .string]
|
||||||
tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t', '\t\t\t\t\t\t\t',
|
tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t', '\t\t\t\t\t', '\t\t\t\t\t\t',
|
||||||
'\t\t\t\t\t\t\t\t', '\t\t\t\t\t\t\t\t\t', '\t\t\t\t\t\t\t\t\t', '\t\t\t\t\t\t\t\t\t']
|
'\t\t\t\t\t\t\t', '\t\t\t\t\t\t\t\t', '\t\t\t\t\t\t\t\t\t', '\t\t\t\t\t\t\t\t\t', '\t\t\t\t\t\t\t\t\t']
|
||||||
)
|
)
|
||||||
|
|
||||||
struct Namespace {
|
struct Namespace {
|
||||||
|
@ -60,8 +60,8 @@ mut:
|
||||||
method_fn_decls map[string][]ast.FnDecl
|
method_fn_decls map[string][]ast.FnDecl
|
||||||
builtin_fns []string // Functions defined in `builtin`
|
builtin_fns []string // Functions defined in `builtin`
|
||||||
empty_line bool
|
empty_line bool
|
||||||
cast_stack []table.Type
|
cast_stack []table.Type
|
||||||
call_stack []ast.CallExpr
|
call_stack []ast.CallExpr
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen(files []ast.File, table &table.Table, pref &pref.Preferences) string {
|
pub fn gen(files []ast.File, table &table.Table, pref &pref.Preferences) string {
|
||||||
|
@ -115,7 +115,7 @@ pub fn gen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
||||||
mut out := g.hashes() + g.definitions.str()
|
mut out := g.hashes() + g.definitions.str()
|
||||||
// equality check for js objects
|
// equality check for js objects
|
||||||
// TODO: Fix msvc bug that's preventing $embed_file('fast_deep_equal.js')
|
// TODO: Fix msvc bug that's preventing $embed_file('fast_deep_equal.js')
|
||||||
//unsafe {
|
// unsafe {
|
||||||
// mut eq_fn := $embed_file('fast_deep_equal.js')
|
// mut eq_fn := $embed_file('fast_deep_equal.js')
|
||||||
// out += eq_fn.data().vstring()
|
// out += eq_fn.data().vstring()
|
||||||
//}
|
//}
|
||||||
|
@ -447,6 +447,9 @@ fn (mut g JsGen) expr(node ast.Expr) {
|
||||||
ast.CTempVar {
|
ast.CTempVar {
|
||||||
g.write('/* ast.CTempVar: node.name */')
|
g.write('/* ast.CTempVar: node.name */')
|
||||||
}
|
}
|
||||||
|
ast.DumpExpr {
|
||||||
|
g.write('/* ast.DumpExpr: $node.expr */')
|
||||||
|
}
|
||||||
ast.AnonFn {
|
ast.AnonFn {
|
||||||
g.gen_fn_decl(node.decl)
|
g.gen_fn_decl(node.decl)
|
||||||
}
|
}
|
||||||
|
@ -689,10 +692,12 @@ 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 := g.table.type_kind(stmt.left_types.first()) in shallow_equatables
|
should_cast := g.table.type_kind(stmt.left_types.first()) in js.shallow_equatables
|
||||||
if should_cast {
|
if should_cast {
|
||||||
g.cast_stack << stmt.left_types.first()
|
g.cast_stack << stmt.left_types.first()
|
||||||
if g.file.mod.name == 'builtin' { g.write('new ') }
|
if g.file.mod.name == 'builtin' {
|
||||||
|
g.write('new ')
|
||||||
|
}
|
||||||
g.write('${g.typ(stmt.left_types.first())}(')
|
g.write('${g.typ(stmt.left_types.first())}(')
|
||||||
}
|
}
|
||||||
g.expr(val)
|
g.expr(val)
|
||||||
|
@ -845,7 +850,9 @@ fn (mut g JsGen) gen_method_decl(it ast.FnDecl) {
|
||||||
}
|
}
|
||||||
g.fn_args(args, it.is_variadic)
|
g.fn_args(args, it.is_variadic)
|
||||||
if it.is_method {
|
if it.is_method {
|
||||||
if args.len > 0 { g.write(', ') }
|
if args.len > 0 {
|
||||||
|
g.write(', ')
|
||||||
|
}
|
||||||
g.write('${it.params[0].name} = this')
|
g.write('${it.params[0].name} = this')
|
||||||
}
|
}
|
||||||
g.writeln(') {')
|
g.writeln(') {')
|
||||||
|
@ -926,13 +933,23 @@ fn (mut g JsGen) gen_for_in_stmt(it ast.ForInStmt) {
|
||||||
if val !in ['', '_'] {
|
if val !in ['', '_'] {
|
||||||
g.write('\tconst $val = ')
|
g.write('\tconst $val = ')
|
||||||
if it.kind == .string {
|
if it.kind == .string {
|
||||||
if g.file.mod.name == 'builtin' { g.write('new ') }
|
if g.file.mod.name == 'builtin' {
|
||||||
|
g.write('new ')
|
||||||
|
}
|
||||||
g.write('byte(')
|
g.write('byte(')
|
||||||
}
|
}
|
||||||
g.expr(it.cond)
|
g.expr(it.cond)
|
||||||
g.write(if it.kind == .array { '.arr' } else if it.kind == .string { '.str' } else { '.val' })
|
g.write(if it.kind == .array {
|
||||||
|
'.arr'
|
||||||
|
} else if it.kind == .string {
|
||||||
|
'.str'
|
||||||
|
} else {
|
||||||
|
'.val'
|
||||||
|
})
|
||||||
g.write('[$i]')
|
g.write('[$i]')
|
||||||
if it.kind == .string { g.write(')') }
|
if it.kind == .string {
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
g.writeln(';')
|
g.writeln(';')
|
||||||
}
|
}
|
||||||
g.stmts(it.stmts)
|
g.stmts(it.stmts)
|
||||||
|
@ -1369,11 +1386,13 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
||||||
r_sym := g.table.get_type_symbol(it.right_type)
|
r_sym := g.table.get_type_symbol(it.right_type)
|
||||||
|
|
||||||
is_not := it.op in [.not_in, .not_is, .ne]
|
is_not := it.op in [.not_in, .not_is, .ne]
|
||||||
if is_not { g.write('!(') }
|
if is_not {
|
||||||
|
g.write('!(')
|
||||||
|
}
|
||||||
|
|
||||||
if it.op == .eq || it.op == .ne {
|
if it.op == .eq || it.op == .ne {
|
||||||
// Shallow equatables
|
// Shallow equatables
|
||||||
if l_sym.kind in shallow_equatables && r_sym.kind in shallow_equatables {
|
if l_sym.kind in js.shallow_equatables && r_sym.kind in js.shallow_equatables {
|
||||||
g.expr(it.left)
|
g.expr(it.left)
|
||||||
g.write('.eq(')
|
g.write('.eq(')
|
||||||
g.expr(it.right)
|
g.expr(it.right)
|
||||||
|
@ -1404,7 +1423,9 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
||||||
'.includes('
|
'.includes('
|
||||||
})
|
})
|
||||||
g.expr(it.left)
|
g.expr(it.left)
|
||||||
if l_sym.kind == .string { g.write('.str') }
|
if l_sym.kind == .string {
|
||||||
|
g.write('.str')
|
||||||
|
}
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else if it.op in [.key_is, .not_is] { // foo is Foo
|
} else if it.op in [.key_is, .not_is] { // foo is Foo
|
||||||
g.expr(it.left)
|
g.expr(it.left)
|
||||||
|
@ -1423,7 +1444,7 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
||||||
g.cast_stack << greater_typ
|
g.cast_stack << greater_typ
|
||||||
}
|
}
|
||||||
g.expr(it.left)
|
g.expr(it.left)
|
||||||
g.write(' ${it.op} ')
|
g.write(' $it.op ')
|
||||||
g.expr(it.right)
|
g.expr(it.right)
|
||||||
|
|
||||||
if is_arithmetic && needs_cast {
|
if is_arithmetic && needs_cast {
|
||||||
|
@ -1432,7 +1453,9 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_not { g.write(')') }
|
if is_not {
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g JsGen) greater_typ(left table.Type, right table.Type) table.Type {
|
fn (mut g JsGen) greater_typ(left table.Type, right table.Type) table.Type {
|
||||||
|
@ -1560,7 +1583,7 @@ fn (mut g JsGen) gen_string_literal(it ast.StringLiteral) {
|
||||||
if g.file.mod.name == 'builtin' {
|
if g.file.mod.name == 'builtin' {
|
||||||
g.write('new ')
|
g.write('new ')
|
||||||
}
|
}
|
||||||
g.write("string(")
|
g.write('string(')
|
||||||
}
|
}
|
||||||
g.write("'$text'")
|
g.write("'$text'")
|
||||||
if should_cast {
|
if should_cast {
|
||||||
|
@ -1651,15 +1674,15 @@ fn (mut g JsGen) gen_integer_literal_expr(it ast.IntegerLiteral) {
|
||||||
// TODO: call.language always seems to be "v", parser bug?
|
// TODO: call.language always seems to be "v", parser bug?
|
||||||
if g.call_stack.len > 0 {
|
if g.call_stack.len > 0 {
|
||||||
call := g.call_stack[g.call_stack.len - 1]
|
call := g.call_stack[g.call_stack.len - 1]
|
||||||
//if call.language == .js {
|
// if call.language == .js {
|
||||||
for t in call.args {
|
for t in call.args {
|
||||||
if t.expr is ast.IntegerLiteral {
|
if t.expr is ast.IntegerLiteral {
|
||||||
if t.expr == it {
|
if t.expr == it {
|
||||||
g.write(it.val)
|
g.write(it.val)
|
||||||
return
|
return
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1685,19 +1708,19 @@ fn (mut g JsGen) gen_float_literal_expr(it ast.FloatLiteral) {
|
||||||
// TODO: call.language always seems to be "v", parser bug?
|
// TODO: call.language always seems to be "v", parser bug?
|
||||||
if g.call_stack.len > 0 {
|
if g.call_stack.len > 0 {
|
||||||
call := g.call_stack[g.call_stack.len - 1]
|
call := g.call_stack[g.call_stack.len - 1]
|
||||||
//if call.language == .js {
|
// if call.language == .js {
|
||||||
for i, t in call.args {
|
for i, t in call.args {
|
||||||
if t.expr is ast.FloatLiteral {
|
if t.expr is ast.FloatLiteral {
|
||||||
if t.expr == it {
|
if t.expr == it {
|
||||||
if call.expected_arg_types[i] in table.integer_type_idxs {
|
if call.expected_arg_types[i] in table.integer_type_idxs {
|
||||||
g.write(int(it.val.f64()).str())
|
g.write(int(it.val.f64()).str())
|
||||||
} else {
|
} else {
|
||||||
g.write(it.val)
|
g.write(it.val)
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -180,6 +180,9 @@ fn (mut w Walker) expr(node ast.Expr) {
|
||||||
w.stmts(node.vweb_tmpl.stmts)
|
w.stmts(node.vweb_tmpl.stmts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast.DumpExpr {
|
||||||
|
w.expr(node.expr)
|
||||||
|
}
|
||||||
ast.GoExpr {
|
ast.GoExpr {
|
||||||
w.expr(node.go_stmt.call_expr)
|
w.expr(node.go_stmt.call_expr)
|
||||||
}
|
}
|
||||||
|
|
|
@ -670,6 +670,7 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
|
||||||
p.label_names << name
|
p.label_names << name
|
||||||
p.next()
|
p.next()
|
||||||
if p.tok.kind == .key_for {
|
if p.tok.kind == .key_for {
|
||||||
|
for_pos := p.tok.position()
|
||||||
mut stmt := p.stmt(is_top_level)
|
mut stmt := p.stmt(is_top_level)
|
||||||
match mut stmt {
|
match mut stmt {
|
||||||
ast.ForStmt {
|
ast.ForStmt {
|
||||||
|
@ -685,7 +686,7 @@ pub fn (mut p Parser) stmt(is_top_level bool) ast.Stmt {
|
||||||
return stmt
|
return stmt
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert false
|
p.error_with_pos('unknown kind of For statement', for_pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1031,7 +1032,7 @@ fn (mut p Parser) parse_multi_expr(is_top_level bool) ast.Stmt {
|
||||||
if node !is ast.CallExpr && (is_top_level || p.tok.kind != .rcbr)
|
if node !is ast.CallExpr && (is_top_level || p.tok.kind != .rcbr)
|
||||||
&& 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.SelectorExpr && node !is ast.DumpExpr {
|
||||||
p.error_with_pos('expression evaluated but not used', node.position())
|
p.error_with_pos('expression evaluated but not used', node.position())
|
||||||
return ast.Stmt{}
|
return ast.Stmt{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,6 +214,17 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||||
pos: spos.extend(p.tok.position())
|
pos: spos.extend(p.tok.position())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.key_dump {
|
||||||
|
spos := p.tok.position()
|
||||||
|
p.next()
|
||||||
|
p.check(.lpar)
|
||||||
|
expr := p.expr(0)
|
||||||
|
p.check(.rpar)
|
||||||
|
node = ast.DumpExpr{
|
||||||
|
expr: expr
|
||||||
|
pos: spos.extend(p.tok.position())
|
||||||
|
}
|
||||||
|
}
|
||||||
.key_offsetof {
|
.key_offsetof {
|
||||||
pos := p.tok.position()
|
pos := p.tok.position()
|
||||||
p.next() // __offsetof
|
p.next() // __offsetof
|
||||||
|
|
|
@ -12,8 +12,9 @@ pub mut:
|
||||||
types []TypeSymbol
|
types []TypeSymbol
|
||||||
type_idxs map[string]int
|
type_idxs map[string]int
|
||||||
fns map[string]Fn
|
fns map[string]Fn
|
||||||
imports []string // List of all imports
|
dumps map[int]string // needed for efficiently generating all _v_dump_expr_TNAME() functions
|
||||||
modules []string // Topologically sorted list of all modules registered by the application
|
imports []string // List of all imports
|
||||||
|
modules []string // Topologically sorted list of all modules registered by the application
|
||||||
cflags []cflag.CFlag
|
cflags []cflag.CFlag
|
||||||
redefined_fns []string
|
redefined_fns []string
|
||||||
fn_gen_types map[string][][]Type // for generic functions
|
fn_gen_types map[string][][]Type // for generic functions
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[vlib/v/tests/inout/dump_expression.vv:2] 1: 1
|
||||||
|
[vlib/v/tests/inout/dump_expression.vv:7] 'a': a
|
||||||
|
[vlib/v/tests/inout/dump_expression.vv:20] point: Point{
|
||||||
|
x: 1
|
||||||
|
y: 2
|
||||||
|
z: 3
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
fn dump_of_int() {
|
||||||
|
x := dump(1) + 1
|
||||||
|
assert x == 2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dump_of_string() {
|
||||||
|
x := dump('a') + 'b'
|
||||||
|
assert x == 'ab'
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Point {
|
||||||
|
mut:
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
z int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dump_of_struct() {
|
||||||
|
point := Point{1, 2, 3}
|
||||||
|
mut x := dump(point)
|
||||||
|
x.x += 100
|
||||||
|
assert x == Point{101, 2, 3}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
dump_of_int()
|
||||||
|
dump_of_string()
|
||||||
|
dump_of_struct()
|
||||||
|
}
|
|
@ -117,6 +117,7 @@ pub enum Kind {
|
||||||
key_true
|
key_true
|
||||||
key_type
|
key_type
|
||||||
key_typeof
|
key_typeof
|
||||||
|
key_dump
|
||||||
key_orelse
|
key_orelse
|
||||||
key_union
|
key_union
|
||||||
key_pub
|
key_pub
|
||||||
|
@ -274,6 +275,7 @@ fn build_token_str() []string {
|
||||||
s[Kind.key_import] = 'import'
|
s[Kind.key_import] = 'import'
|
||||||
s[Kind.key_unsafe] = 'unsafe'
|
s[Kind.key_unsafe] = 'unsafe'
|
||||||
s[Kind.key_typeof] = 'typeof'
|
s[Kind.key_typeof] = 'typeof'
|
||||||
|
s[Kind.key_dump] = 'dump'
|
||||||
s[Kind.key_enum] = 'enum'
|
s[Kind.key_enum] = 'enum'
|
||||||
s[Kind.key_interface] = 'interface'
|
s[Kind.key_interface] = 'interface'
|
||||||
s[Kind.key_pub] = 'pub'
|
s[Kind.key_pub] = 'pub'
|
||||||
|
|
|
@ -42,7 +42,7 @@ pub fn new_mod_file_cacher() &ModFileCacher {
|
||||||
return &ModFileCacher{}
|
return &ModFileCacher{}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mcache &ModFileCacher) dump() {
|
pub fn (mcache &ModFileCacher) debug() {
|
||||||
$if debug {
|
$if debug {
|
||||||
eprintln('ModFileCacher DUMP:')
|
eprintln('ModFileCacher DUMP:')
|
||||||
eprintln(' ModFileCacher.cache:')
|
eprintln(' ModFileCacher.cache:')
|
||||||
|
|
Loading…
Reference in New Issue