v.parser, v.checker, v.gen: add support for [translated] tag (#13373)
parent
054c8b1f13
commit
cec7e91714
|
@ -674,6 +674,7 @@ pub:
|
|||
global_scope &Scope
|
||||
is_test bool // true for _test.v files
|
||||
is_generated bool // true for `[generated] module xyz` files; turn off notices
|
||||
is_translated bool // true for `[translated] module xyz` files; turn off some checks
|
||||
pub mut:
|
||||
path string // absolute path of the source file - '/projects/v/file.v'
|
||||
path_base string // file name - 'file.v' (useful for tracing)
|
||||
|
|
|
@ -177,7 +177,7 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
|||
}
|
||||
if obj.is_stack_obj && !c.inside_unsafe {
|
||||
type_sym := c.table.sym(obj.typ.set_nr_muls(0))
|
||||
if !type_sym.is_heap() && !c.pref.translated {
|
||||
if !type_sym.is_heap() && !c.pref.translated && !c.file.is_translated {
|
||||
suggestion := if type_sym.kind == .struct_ {
|
||||
'declaring `$type_sym.name` as `[heap]`'
|
||||
} else {
|
||||
|
@ -278,7 +278,7 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
|||
ast.PrefixExpr {
|
||||
// Do now allow `*x = y` outside `unsafe`
|
||||
if left.op == .mul {
|
||||
if !c.inside_unsafe && !c.pref.translated {
|
||||
if !c.inside_unsafe && !c.pref.translated && !c.file.is_translated {
|
||||
c.error('modifying variables via dereferencing can only be done in `unsafe` blocks',
|
||||
node.pos)
|
||||
} else {
|
||||
|
@ -325,7 +325,7 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
|||
// right type was a generic `T`
|
||||
continue
|
||||
}
|
||||
if c.pref.translated {
|
||||
if c.pref.translated || c.file.is_translated {
|
||||
// TODO fix this in C2V instead, for example cast enums to int before using `|` on them.
|
||||
// TODO replace all c.pref.translated checks with `$if !translated` for performance
|
||||
continue
|
||||
|
|
|
@ -369,7 +369,7 @@ fn (mut c Checker) check_shift(mut node ast.InfixExpr, left_type ast.Type, right
|
|||
ast.u64_type { 63 }
|
||||
else { 64 }
|
||||
}
|
||||
if ival > moffset && !c.pref.translated {
|
||||
if ival > moffset && !c.pref.translated && !c.file.is_translated {
|
||||
c.error('shift count for type `$left_sym_final.name` too large (maximum: $moffset bits)',
|
||||
node.right.pos())
|
||||
return left_type
|
||||
|
|
|
@ -390,11 +390,13 @@ fn (mut c Checker) file_has_main_fn(file &ast.File) bool {
|
|||
}
|
||||
|
||||
fn (mut c Checker) check_valid_snake_case(name string, identifier string, pos token.Pos) {
|
||||
if !c.pref.is_vweb && !c.pref.translated && name.len > 0
|
||||
&& (name[0] == `_` || name.contains('._')) {
|
||||
if c.pref.translated || c.file.is_translated {
|
||||
return
|
||||
}
|
||||
if !c.pref.is_vweb && name.len > 0 && (name[0] == `_` || name.contains('._')) {
|
||||
c.error('$identifier `$name` cannot start with `_`', pos)
|
||||
}
|
||||
if !c.pref.experimental && !c.pref.translated && util.contains_capital(name) {
|
||||
if !c.pref.experimental && util.contains_capital(name) {
|
||||
c.error('$identifier `$name` cannot contain uppercase letters, use snake_case instead',
|
||||
pos)
|
||||
}
|
||||
|
@ -407,7 +409,7 @@ fn stripped_name(name string) string {
|
|||
|
||||
fn (mut c Checker) check_valid_pascal_case(name string, identifier string, pos token.Pos) {
|
||||
sname := stripped_name(name)
|
||||
if sname.len > 0 && !sname[0].is_capital() && !c.pref.translated {
|
||||
if sname.len > 0 && !sname[0].is_capital() && !c.pref.translated && !c.file.is_translated {
|
||||
c.error('$identifier `$name` must begin with capital letter', pos)
|
||||
}
|
||||
}
|
||||
|
@ -952,7 +954,7 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||
return ast.void_type
|
||||
}
|
||||
.and, .logical_or {
|
||||
if !c.pref.translated {
|
||||
if !c.pref.translated && !c.file.is_translated {
|
||||
if node.left_type != ast.bool_type_idx {
|
||||
c.error('left operand for `$node.op` is not a boolean', node.left.pos())
|
||||
}
|
||||
|
@ -987,7 +989,7 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||
c.error('only `==`, `!=`, `|` and `&` are defined on `[flag]` tagged `enum`, use an explicit cast to `int` if needed',
|
||||
node.pos)
|
||||
}
|
||||
} else if !c.pref.translated {
|
||||
} else if !c.pref.translated && !c.file.is_translated {
|
||||
// Regular enums
|
||||
c.error('only `==` and `!=` are defined on `enum`, use an explicit cast to `int` if needed',
|
||||
node.pos)
|
||||
|
@ -1008,7 +1010,8 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||
}
|
||||
// Dual sides check (compatibility check)
|
||||
if !(c.symmetric_check(left_type, right_type) && c.symmetric_check(right_type, left_type))
|
||||
&& !c.pref.translated && !node.left.is_auto_deref_var() && !node.right.is_auto_deref_var() {
|
||||
&& !c.pref.translated && !c.file.is_translated && !node.left.is_auto_deref_var()
|
||||
&& !node.right.is_auto_deref_var() {
|
||||
// for type-unresolved consts
|
||||
if left_type == ast.void_type || right_type == ast.void_type {
|
||||
return ast.void_type
|
||||
|
@ -1047,7 +1050,7 @@ fn (mut c Checker) fail_if_immutable(expr ast.Expr) (string, token.Pos) {
|
|||
ast.Ident {
|
||||
if expr.obj is ast.Var {
|
||||
mut v := expr.obj as ast.Var
|
||||
if !v.is_mut && !c.pref.translated && !c.inside_unsafe {
|
||||
if !v.is_mut && !c.pref.translated && !c.file.is_translated && !c.inside_unsafe {
|
||||
c.error('`$expr.name` is immutable, declare it with `mut` to make it mutable',
|
||||
expr.pos)
|
||||
}
|
||||
|
@ -1137,7 +1140,7 @@ fn (mut c Checker) fail_if_immutable(expr ast.Expr) (string, token.Pos) {
|
|||
pos = expr.pos
|
||||
}
|
||||
} else {
|
||||
if !field_info.is_mut && !c.pref.translated {
|
||||
if !field_info.is_mut && !c.pref.translated && !c.file.is_translated {
|
||||
type_str := c.table.type_to_str(expr.expr_type)
|
||||
c.error('field `$expr.field_name` of struct `$type_str` is immutable',
|
||||
expr.pos)
|
||||
|
@ -1696,7 +1699,8 @@ pub fn (mut c Checker) enum_decl(mut node ast.EnumDecl) {
|
|||
val := field.expr.val.i64()
|
||||
if val < checker.int_min || val > checker.int_max {
|
||||
c.error('enum value `$val` overflows int', field.expr.pos)
|
||||
} else if !c.pref.translated && !node.is_multi_allowed && i64(val) in seen {
|
||||
} else if !c.pref.translated && !c.file.is_translated && !node.is_multi_allowed
|
||||
&& i64(val) in seen {
|
||||
c.error('enum value `$val` already exists', field.expr.pos)
|
||||
}
|
||||
seen << i64(val)
|
||||
|
@ -1728,7 +1732,8 @@ pub fn (mut c Checker) enum_decl(mut node ast.EnumDecl) {
|
|||
last := seen[seen.len - 1]
|
||||
if last == checker.int_max {
|
||||
c.error('enum value overflows', field.pos)
|
||||
} else if !c.pref.translated && !node.is_multi_allowed && last + 1 in seen {
|
||||
} else if !c.pref.translated && !c.file.is_translated && !node.is_multi_allowed
|
||||
&& last + 1 in seen {
|
||||
c.error('enum value `${last + 1}` already exists', field.pos)
|
||||
}
|
||||
seen << last + 1
|
||||
|
@ -2720,7 +2725,7 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
|
|||
}
|
||||
}
|
||||
} else if to_type == ast.bool_type && from_type != ast.bool_type && !c.inside_unsafe
|
||||
&& !c.pref.translated {
|
||||
&& !c.pref.translated && !c.file.is_translated {
|
||||
c.error('cannot cast to bool - use e.g. `some_int != 0` instead', node.pos)
|
||||
} else if from_type == ast.none_type && !to_type.has_flag(.optional) {
|
||||
type_name := c.table.type_to_str(to_type)
|
||||
|
@ -3404,21 +3409,16 @@ pub fn (mut c Checker) mark_as_referenced(mut node ast.Expr, as_interface bool)
|
|||
obj = c.fn_scope.find_var(node.obj.name) or { obj }
|
||||
}
|
||||
type_sym := c.table.sym(obj.typ.set_nr_muls(0))
|
||||
if obj.is_stack_obj && !type_sym.is_heap() && !c.pref.translated {
|
||||
if obj.is_stack_obj && !type_sym.is_heap() && !c.pref.translated
|
||||
&& !c.file.is_translated {
|
||||
suggestion := if type_sym.kind == .struct_ {
|
||||
'declaring `$type_sym.name` as `[heap]`'
|
||||
} else {
|
||||
'wrapping the `$type_sym.name` object in a `struct` declared as `[heap]`'
|
||||
}
|
||||
if !c.pref.translated {
|
||||
mischief := if as_interface {
|
||||
'used as interface object'
|
||||
} else {
|
||||
'referenced'
|
||||
}
|
||||
mischief := if as_interface { 'used as interface object' } else { 'referenced' }
|
||||
c.error('`$node.name` cannot be $mischief outside `unsafe` blocks as it might be stored on stack. Consider ${suggestion}.',
|
||||
node.pos)
|
||||
}
|
||||
} else if type_sym.kind == .array_fixed {
|
||||
c.error('cannot reference fixed array `$node.name` outside `unsafe` blocks as it is supposed to be stored on stack',
|
||||
node.pos)
|
||||
|
@ -3532,15 +3532,16 @@ pub fn (mut c Checker) prefix_expr(mut node ast.PrefixExpr) ast.Type {
|
|||
if right_type.is_ptr() {
|
||||
return right_type.deref()
|
||||
}
|
||||
if !right_type.is_pointer() && !c.pref.translated {
|
||||
if !right_type.is_pointer() && !c.pref.translated && !c.file.is_translated {
|
||||
s := c.table.type_to_str(right_type)
|
||||
c.error('invalid indirect of `$s`', node.pos)
|
||||
}
|
||||
}
|
||||
if node.op == .bit_not && !right_type.is_int() && !c.pref.translated {
|
||||
if node.op == .bit_not && !right_type.is_int() && !c.pref.translated && !c.file.is_translated {
|
||||
c.error('operator ~ only defined on int types', node.pos)
|
||||
}
|
||||
if node.op == .not && right_type != ast.bool_type_idx && !c.pref.translated {
|
||||
if node.op == .not && right_type != ast.bool_type_idx && !c.pref.translated
|
||||
&& !c.file.is_translated {
|
||||
c.error('! operator can only be used with bool types', node.pos)
|
||||
}
|
||||
// FIXME
|
||||
|
@ -3654,7 +3655,7 @@ pub fn (mut c Checker) index_expr(mut node ast.IndexExpr) ast.Type {
|
|||
is_ok = v.is_mut && v.is_arg && !typ.deref().is_ptr()
|
||||
}
|
||||
}
|
||||
if !is_ok && !c.pref.translated {
|
||||
if !is_ok && !c.pref.translated && !c.file.is_translated {
|
||||
c.warn('pointer indexing is only allowed in `unsafe` blocks', node.pos)
|
||||
}
|
||||
}
|
||||
|
@ -3736,7 +3737,7 @@ pub fn (mut c Checker) enum_val(mut node ast.EnumVal) ast.Type {
|
|||
}
|
||||
}
|
||||
mut typ := ast.new_type(typ_idx)
|
||||
if c.pref.translated {
|
||||
if c.pref.translated || c.file.is_translated {
|
||||
// TODO make more strict
|
||||
node.typ = typ
|
||||
return typ
|
||||
|
@ -3752,7 +3753,7 @@ pub fn (mut c Checker) enum_val(mut node ast.EnumVal) ast.Type {
|
|||
typ_sym = c.table.sym(typ)
|
||||
}
|
||||
fsym := c.table.final_sym(typ)
|
||||
if fsym.kind != .enum_ && !c.pref.translated {
|
||||
if fsym.kind != .enum_ && !c.pref.translated && !c.file.is_translated {
|
||||
// TODO in C int fields can be compared to enums, need to handle that in C2V
|
||||
c.error('expected type is not an enum (`$typ_sym.name`)', node.pos)
|
||||
return ast.void_type
|
||||
|
@ -3839,7 +3840,7 @@ pub fn (mut c Checker) error(message string, pos token.Pos) {
|
|||
print_backtrace()
|
||||
exit(1)
|
||||
}
|
||||
if c.pref.translated && message.starts_with('mismatched types') {
|
||||
if (c.pref.translated || c.file.is_translated) && message.starts_with('mismatched types') {
|
||||
// TODO move this
|
||||
return
|
||||
}
|
||||
|
|
|
@ -207,7 +207,8 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if c.pref.translated && node.is_variadic && node.params.len == 1 && param.typ.is_ptr() {
|
||||
if (c.pref.translated || c.file.is_translated) && node.is_variadic
|
||||
&& node.params.len == 1 && param.typ.is_ptr() {
|
||||
// TODO c2v hack to fix `(const char *s, ...)`
|
||||
param.typ = ast.int_type.ref()
|
||||
}
|
||||
|
@ -679,7 +680,7 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||
}
|
||||
node.is_keep_alive = func.is_keep_alive
|
||||
if func.mod != 'builtin' && func.language == .v && func.no_body && !c.pref.translated
|
||||
&& !func.is_unsafe {
|
||||
&& !c.file.is_translated && !func.is_unsafe {
|
||||
c.error('cannot call a function that does not have a body', node.pos)
|
||||
}
|
||||
for concrete_type in node.concrete_types {
|
||||
|
@ -827,7 +828,8 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||
if call_arg.typ != param.typ
|
||||
&& (param.typ == ast.voidptr_type || final_param_sym.idx == ast.voidptr_type_idx)
|
||||
&& !call_arg.typ.is_any_kind_of_pointer() && func.language == .v
|
||||
&& !call_arg.expr.is_lvalue() && func.name != 'json.encode' && !c.pref.translated {
|
||||
&& !call_arg.expr.is_lvalue() && func.name != 'json.encode' && !c.pref.translated
|
||||
&& !c.file.is_translated {
|
||||
c.error('expression cannot be passed as `voidptr`', call_arg.expr.pos())
|
||||
}
|
||||
// Handle expected interface
|
||||
|
@ -853,7 +855,7 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||
if param.typ.has_flag(.generic) {
|
||||
continue
|
||||
}
|
||||
if c.pref.translated {
|
||||
if c.pref.translated || c.file.is_translated {
|
||||
// TODO duplicated logic in check_types() (check_types.v)
|
||||
// Allow enums to be used as ints and vice versa in translated code
|
||||
if param.typ == ast.int_type && typ_sym.kind == .enum_ {
|
||||
|
|
|
@ -144,7 +144,7 @@ fn (mut c Checker) for_stmt(mut node ast.ForStmt) {
|
|||
prev_loop_label := c.loop_label
|
||||
c.expected_type = ast.bool_type
|
||||
typ := c.expr(node.cond)
|
||||
if !node.is_inf && typ.idx() != ast.bool_type_idx && !c.pref.translated {
|
||||
if !node.is_inf && typ.idx() != ast.bool_type_idx && !c.pref.translated && !c.file.is_translated {
|
||||
c.error('non-bool used as for condition', node.pos)
|
||||
}
|
||||
if mut node.cond is ast.InfixExpr {
|
||||
|
|
|
@ -28,7 +28,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
|
|||
mut is_comptime_type_is_expr := false // if `$if T is string`
|
||||
for i in 0 .. node.branches.len {
|
||||
mut branch := node.branches[i]
|
||||
if branch.cond is ast.ParExpr && !c.pref.translated {
|
||||
if branch.cond is ast.ParExpr && !c.pref.translated && !c.file.is_translated {
|
||||
c.error('unnecessary `()` in `$if_kind` condition, use `$if_kind expr {` instead of `$if_kind (expr) {`.',
|
||||
branch.pos)
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
|
|||
c.expected_type = ast.bool_type
|
||||
cond_typ := c.unwrap_generic(c.expr(branch.cond))
|
||||
if (cond_typ.idx() != ast.bool_type_idx || cond_typ.has_flag(.optional))
|
||||
&& !c.pref.translated {
|
||||
&& !c.pref.translated && !c.file.is_translated {
|
||||
c.error('non-bool type `${c.table.type_to_str(cond_typ)}` used as if condition',
|
||||
branch.cond.pos())
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import strings
|
|||
pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
|
||||
node.is_expr = c.expected_type != ast.void_type
|
||||
node.expected_type = c.expected_type
|
||||
if mut node.cond is ast.ParExpr && !c.pref.translated {
|
||||
if mut node.cond is ast.ParExpr && !c.pref.translated && !c.file.is_translated {
|
||||
c.error('unnecessary `()` in `match` condition, use `match expr {` instead of `match (expr) {`.',
|
||||
node.cond.pos)
|
||||
}
|
||||
|
@ -333,7 +333,7 @@ fn (mut c Checker) match_exprs(mut node ast.MatchExpr, cond_type_sym ast.TypeSym
|
|||
}
|
||||
}
|
||||
if is_exhaustive {
|
||||
if has_else && !c.pref.translated {
|
||||
if has_else && !c.pref.translated && !c.file.is_translated {
|
||||
c.error('match expression is exhaustive, `else` is unnecessary', else_branch.pos)
|
||||
}
|
||||
return
|
||||
|
|
|
@ -113,7 +113,7 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) {
|
|||
}
|
||||
if (exp_type.is_ptr() || exp_type.is_pointer())
|
||||
&& (!got_typ.is_ptr() && !got_typ.is_pointer()) && got_typ != ast.int_literal_type
|
||||
&& !c.pref.translated {
|
||||
&& !c.pref.translated && !c.file.is_translated {
|
||||
pos := node.exprs[i].pos()
|
||||
if node.exprs[i].is_auto_deref_var() {
|
||||
continue
|
||||
|
@ -131,7 +131,7 @@ pub fn (mut c Checker) return_stmt(mut node ast.Return) {
|
|||
}
|
||||
if obj.is_stack_obj && !c.inside_unsafe {
|
||||
type_sym := c.table.sym(obj.typ.set_nr_muls(0))
|
||||
if !type_sym.is_heap() && !c.pref.translated {
|
||||
if !type_sym.is_heap() && !c.pref.translated && !c.file.is_translated {
|
||||
suggestion := if type_sym.kind == .struct_ {
|
||||
'declaring `$type_sym.name` as `[heap]`'
|
||||
} else {
|
||||
|
|
|
@ -313,7 +313,7 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
|
|||
}
|
||||
if obj.is_stack_obj && !c.inside_unsafe {
|
||||
sym := c.table.sym(obj.typ.set_nr_muls(0))
|
||||
if !sym.is_heap() && !c.pref.translated {
|
||||
if !sym.is_heap() && !c.pref.translated && !c.file.is_translated {
|
||||
suggestion := if sym.kind == .struct_ {
|
||||
'declaring `$sym.name` as `[heap]`'
|
||||
} else {
|
||||
|
@ -348,7 +348,7 @@ pub fn (mut c Checker) struct_init(mut node ast.StructInit) ast.Type {
|
|||
continue
|
||||
}
|
||||
if field.typ.is_ptr() && !field.typ.has_flag(.shared_f) && !node.has_update_expr
|
||||
&& !c.pref.translated {
|
||||
&& !c.pref.translated && !c.file.is_translated {
|
||||
c.error('reference field `${type_sym.name}.$field.name` must be initialized',
|
||||
node.pos)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
vlib/v/checker/tests/static_vars_in_translated_mode.vv:2:13: error: static variables are supported only in -translated mode or in [unsafe] fn
|
||||
vlib/v/checker/tests/static_vars_in_translated_mode.vv:2:13: error: static variables are supported only in translated mode or in [unsafe] fn
|
||||
1 | fn counter() int {
|
||||
2 | mut static icounter := 0
|
||||
| ~~~~~~~~
|
||||
|
|
|
@ -4474,7 +4474,7 @@ fn (mut g Gen) ident(node ast.Ident) {
|
|||
}
|
||||
}
|
||||
} else if node_info is ast.IdentFn {
|
||||
if g.pref.translated {
|
||||
if g.pref.translated || g.file.is_translated {
|
||||
// `p_mobjthinker` => `P_MobjThinker`
|
||||
if f := g.table.find_fn(node.name) {
|
||||
// TODO PERF fn lookup for each fn call in translated mode
|
||||
|
@ -4511,7 +4511,7 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) {
|
|||
g.expr(node.expr)
|
||||
} else {
|
||||
styp := g.typ(node.typ)
|
||||
if g.pref.translated && sym.kind == .function {
|
||||
if (g.pref.translated || g.file.is_translated) && sym.kind == .function {
|
||||
// TODO handle the type in fn casts, not just exprs
|
||||
/*
|
||||
info := sym.info as ast.FnType
|
||||
|
|
|
@ -436,7 +436,7 @@ fn (mut g Gen) c_fn_name(node &ast.FnDecl) ?string {
|
|||
name = g.generic_fn_name(g.cur_concrete_types, name, true)
|
||||
}
|
||||
|
||||
if g.pref.translated && node.attrs.contains('c') {
|
||||
if (g.pref.translated || g.file.is_translated) && node.attrs.contains('c') {
|
||||
// This fixes unknown symbols errors when building separate .c => .v files
|
||||
// into .o files
|
||||
//
|
||||
|
@ -1176,7 +1176,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
|||
} else {
|
||||
name = c_name(name)
|
||||
}
|
||||
if g.pref.translated {
|
||||
if g.pref.translated || g.file.is_translated {
|
||||
// For `[c: 'P_TryMove'] fn p_trymove( ... `
|
||||
// every time `p_trymove` is called, `P_TryMove` must be generated instead.
|
||||
if f := g.table.find_fn(node.name) {
|
||||
|
@ -1573,7 +1573,7 @@ fn (mut g Gen) call_args(node ast.CallExpr) {
|
|||
}
|
||||
}
|
||||
elem_type := g.typ(arr_info.elem_type)
|
||||
if g.pref.translated && args.len == 1 {
|
||||
if (g.pref.translated || g.file.is_translated) && args.len == 1 {
|
||||
// Handle `foo(c'str')` for `fn foo(args ...&u8)`
|
||||
// TODOC2V handle this in a better place
|
||||
// println(g.table.type_to_str(args[0].typ))
|
||||
|
|
|
@ -158,8 +158,9 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
|
|||
iv := lx.info as ast.IdentVar
|
||||
share = iv.share
|
||||
if iv.is_static {
|
||||
if !p.pref.translated && !p.pref.is_fmt && !p.inside_unsafe_fn {
|
||||
return p.error_with_pos('static variables are supported only in -translated mode or in [unsafe] fn',
|
||||
if !p.pref.translated && !p.is_translated && !p.pref.is_fmt
|
||||
&& !p.inside_unsafe_fn {
|
||||
return p.error_with_pos('static variables are supported only in translated mode or in [unsafe] fn',
|
||||
lx.pos)
|
||||
}
|
||||
is_static = true
|
||||
|
|
|
@ -255,7 +255,8 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
|||
if p.tok.kind == .name {
|
||||
// TODO high order fn
|
||||
name = if language == .js { p.check_js_name() } else { p.check_name() }
|
||||
if language == .v && !p.pref.translated && util.contains_capital(name) && !p.builtin_mod {
|
||||
if language == .v && !p.pref.translated && !p.is_translated && util.contains_capital(name)
|
||||
&& !p.builtin_mod {
|
||||
p.error_with_pos('function names cannot contain uppercase letters, use snake_case instead',
|
||||
name_pos)
|
||||
return ast.FnDecl{
|
||||
|
|
|
@ -63,6 +63,7 @@ mut:
|
|||
is_manualfree bool // true when `[manualfree] module abc`, makes *all* fns in the current .v file, opt out of autofree
|
||||
has_globals bool // `[has_globals] module abc` - allow globals declarations, even without -enable-globals, in that single .v file __only__
|
||||
is_generated bool // `[generated] module abc` - turn off compiler notices for that single .v file __only__.
|
||||
is_translated bool // `[translated] module abc` - mark a file as translated, to relax some compiler checks for translated code.
|
||||
attrs []ast.Attr // attributes before next decl stmt
|
||||
expr_mod string // for constructing full type names in parse_type()
|
||||
scope &ast.Scope
|
||||
|
@ -324,6 +325,7 @@ pub fn (mut p Parser) parse() &ast.File {
|
|||
path_base: p.file_base
|
||||
is_test: p.inside_test_file
|
||||
is_generated: p.is_generated
|
||||
is_translated: p.is_translated
|
||||
nr_lines: p.scanner.line_nr
|
||||
nr_bytes: p.scanner.text.len
|
||||
mod: module_decl
|
||||
|
@ -1886,7 +1888,7 @@ fn (mut p Parser) parse_multi_expr(is_top_level bool) ast.Stmt {
|
|||
// TODO remove translated
|
||||
if p.tok.kind in [.assign, .decl_assign] || p.tok.kind.is_assign() {
|
||||
return p.partial_assign_stmt(left, left_comments)
|
||||
} else if !p.pref.translated && !p.pref.is_fmt
|
||||
} else if !p.pref.translated && !p.is_translated && !p.pref.is_fmt
|
||||
&& tok.kind !in [.key_if, .key_match, .key_lock, .key_rlock, .key_select] {
|
||||
for node in left {
|
||||
if (is_top_level || p.tok.kind != .rcbr) && node !is ast.CallExpr
|
||||
|
@ -3046,6 +3048,9 @@ fn (mut p Parser) module_decl() ast.Module {
|
|||
ma.pos)
|
||||
}
|
||||
}
|
||||
'translated' {
|
||||
p.is_translated = true
|
||||
}
|
||||
else {
|
||||
p.error_with_pos('unknown module attribute `[$ma.name]`', ma.pos)
|
||||
return mod_node
|
||||
|
@ -3315,7 +3320,7 @@ fn (mut p Parser) global_decl() ast.GlobalDecl {
|
|||
}
|
||||
|
||||
if !p.has_globals && !p.pref.enable_globals && !p.pref.is_fmt && !p.pref.translated
|
||||
&& !p.pref.is_livemain && !p.pref.building_v && !p.builtin_mod {
|
||||
&& !p.is_translated && !p.pref.is_livemain && !p.pref.building_v && !p.builtin_mod {
|
||||
p.error('use `v -enable-globals ...` to enable globals')
|
||||
return ast.GlobalDecl{}
|
||||
}
|
||||
|
|
|
@ -53,8 +53,8 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|
|||
p.error('`$p.tok.lit` lacks body')
|
||||
return ast.StructDecl{}
|
||||
}
|
||||
if language == .v && !p.builtin_mod && name.len > 0 && !name[0].is_capital()
|
||||
&& !p.pref.translated {
|
||||
if language == .v && !p.builtin_mod && !p.is_translated && name.len > 0 && !name[0].is_capital()
|
||||
&& !p.pref.translated && !p.is_translated {
|
||||
p.error_with_pos('struct name `$name` must begin with capital letter', name_pos)
|
||||
return ast.StructDecl{}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
[translated]
|
||||
module main
|
||||
|
||||
import math
|
||||
|
||||
fn test_NotSnakeCaseFunction() {}
|
Loading…
Reference in New Issue