all: mutability check (part 1); enable mutable sumtype args
parent
1ee0939f69
commit
624f22e27e
|
@ -145,7 +145,7 @@ pub fn (a array) repeat(count int) array {
|
||||||
|
|
||||||
// array.sort sorts array in-place using given `compare` function as comparator
|
// array.sort sorts array in-place using given `compare` function as comparator
|
||||||
pub fn (mut a array) sort_with_compare(compare voidptr) {
|
pub fn (mut a array) sort_with_compare(compare voidptr) {
|
||||||
C.qsort(a.data, a.len, a.element_size, compare)
|
C.qsort(mut a.data, a.len, a.element_size, compare)
|
||||||
}
|
}
|
||||||
|
|
||||||
// array.insert
|
// array.insert
|
||||||
|
|
|
@ -274,7 +274,7 @@ fn f64_to_decimal(mant u64, exp u64) Dec64 {
|
||||||
e10 = int(q) + e2
|
e10 = int(q) + e2
|
||||||
i := -e2 - int(q)
|
i := -e2 - int(q)
|
||||||
k := pow5_bits(i) - pow5_num_bits_64
|
k := pow5_bits(i) - pow5_num_bits_64
|
||||||
mut j := int(q) - k
|
j := int(q) - k
|
||||||
mul := pow5_split_64[i]
|
mul := pow5_split_64[i]
|
||||||
vr = mul_shift_64(u64(4) * m2 , mul, j)
|
vr = mul_shift_64(u64(4) * m2 , mul, j)
|
||||||
vp = mul_shift_64(u64(4) * m2 + u64(2) , mul, j)
|
vp = mul_shift_64(u64(4) * m2 + u64(2) , mul, j)
|
||||||
|
|
|
@ -777,7 +777,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
|
||||||
if ch in [`f`, `F`] {
|
if ch in [`f`, `F`] {
|
||||||
v_sprintf_panic(p_index, pt.len)
|
v_sprintf_panic(p_index, pt.len)
|
||||||
x := unsafe {*(&f64(pt[p_index]))}
|
x := unsafe {*(&f64(pt[p_index]))}
|
||||||
mut positive := x >= f64(0.0)
|
positive := x >= f64(0.0)
|
||||||
len1 = if len1 >= 0 { len1 } else { def_len1 }
|
len1 = if len1 >= 0 { len1 } else { def_len1 }
|
||||||
s := format_fl(f64(x), {pad_ch: pad_ch, len0: len0, len1: len1, positive: positive, sign_flag: sign, allign: allign})
|
s := format_fl(f64(x), {pad_ch: pad_ch, len0: len0, len1: len1, positive: positive, sign_flag: sign, allign: allign})
|
||||||
res.write(if ch == `F` {s.to_upper()} else {s})
|
res.write(if ch == `F` {s.to_upper()} else {s})
|
||||||
|
@ -789,7 +789,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
|
||||||
else if ch in [`e`, `E`] {
|
else if ch in [`e`, `E`] {
|
||||||
v_sprintf_panic(p_index, pt.len)
|
v_sprintf_panic(p_index, pt.len)
|
||||||
x := unsafe {*(&f64(pt[p_index]))}
|
x := unsafe {*(&f64(pt[p_index]))}
|
||||||
mut positive := x >= f64(0.0)
|
positive := x >= f64(0.0)
|
||||||
len1 = if len1 >= 0 { len1 } else { def_len1 }
|
len1 = if len1 >= 0 { len1 } else { def_len1 }
|
||||||
s := format_es(f64(x), {pad_ch: pad_ch, len0: len0, len1: len1, positive: positive, sign_flag: sign, allign: allign})
|
s := format_es(f64(x), {pad_ch: pad_ch, len0: len0, len1: len1, positive: positive, sign_flag: sign, allign: allign})
|
||||||
res.write(if ch == `E` {s.to_upper()} else {s})
|
res.write(if ch == `E` {s.to_upper()} else {s})
|
||||||
|
@ -801,7 +801,7 @@ pub fn v_sprintf(str string, pt ... voidptr) string{
|
||||||
else if ch in [`g`, `G`] {
|
else if ch in [`g`, `G`] {
|
||||||
v_sprintf_panic(p_index, pt.len)
|
v_sprintf_panic(p_index, pt.len)
|
||||||
x := unsafe {*(&f64(pt[p_index]))}
|
x := unsafe {*(&f64(pt[p_index]))}
|
||||||
mut positive := x >= f64(0.0)
|
positive := x >= f64(0.0)
|
||||||
mut s := ""
|
mut s := ""
|
||||||
tx := fabs(x)
|
tx := fabs(x)
|
||||||
if tx < 999_999.0 && tx >= 0.00001 {
|
if tx < 999_999.0 && tx >= 0.00001 {
|
||||||
|
|
|
@ -55,17 +55,17 @@ pub fn parse_rfc2822(s string) ?Time {
|
||||||
// also checks and support for leapseconds should be added in future PR
|
// also checks and support for leapseconds should be added in future PR
|
||||||
pub fn parse_iso8601(s string) ?Time {
|
pub fn parse_iso8601(s string) ?Time {
|
||||||
|
|
||||||
mut year := 0
|
year := 0
|
||||||
mut month := 0
|
month := 0
|
||||||
mut day := 0
|
day := 0
|
||||||
mut hour := 0
|
hour := 0
|
||||||
mut minute := 0
|
minute := 0
|
||||||
mut second := 0
|
second := 0
|
||||||
mut mic_second := 0
|
mic_second := 0
|
||||||
mut time_char := `a`
|
time_char := `a`
|
||||||
mut plus_min := `a`
|
plus_min := `a`
|
||||||
mut offset_hour := 0
|
offset_hour := 0
|
||||||
mut offset_min := 0
|
offset_min := 0
|
||||||
|
|
||||||
count := unsafe {C.sscanf(charptr(s.str), "%4d-%2d-%2d%c%2d:%2d:%2d.%6d%c%2d:%2d", &year, &month, &day,
|
count := unsafe {C.sscanf(charptr(s.str), "%4d-%2d-%2d%c%2d:%2d:%2d.%6d%c%2d:%2d", &year, &month, &day,
|
||||||
&time_char, &hour, &minute,
|
&time_char, &hour, &minute,
|
||||||
|
|
|
@ -12,9 +12,9 @@ pub type TypeDecl = AliasTypeDecl | FnTypeDecl | SumTypeDecl
|
||||||
pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | BoolLiteral | CallExpr | CastExpr |
|
pub type Expr = AnonFn | ArrayInit | AsCast | Assoc | BoolLiteral | CallExpr | CastExpr |
|
||||||
ChanInit | CharLiteral | Comment | ComptimeCall | ConcatExpr | EnumVal | FloatLiteral |
|
ChanInit | CharLiteral | Comment | ComptimeCall | ConcatExpr | EnumVal | FloatLiteral |
|
||||||
Ident | IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr |
|
Ident | IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr |
|
||||||
MapInit | MatchExpr | None | OrExpr | ParExpr | PostfixExpr | PrefixExpr | RangeExpr | SelectExpr |
|
MapInit | MatchExpr | None | OrExpr | ParExpr | PostfixExpr | PrefixExpr | RangeExpr |
|
||||||
SelectorExpr | SizeOf | SqlExpr | StringInterLiteral | StringLiteral | StructInit | Type |
|
SelectExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral | StringLiteral | StructInit |
|
||||||
TypeOf | UnsafeExpr
|
Type | TypeOf | UnsafeExpr
|
||||||
|
|
||||||
pub type Stmt = AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDecl | DeferStmt |
|
pub type Stmt = AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDecl | DeferStmt |
|
||||||
EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl | GoStmt |
|
EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | GlobalDecl | GoStmt |
|
||||||
|
@ -491,8 +491,8 @@ pub mut:
|
||||||
|
|
||||||
pub struct UnsafeExpr {
|
pub struct UnsafeExpr {
|
||||||
pub:
|
pub:
|
||||||
expr Expr
|
expr Expr
|
||||||
pos token.Position
|
pos token.Position
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LockExpr {
|
pub struct LockExpr {
|
||||||
|
@ -966,7 +966,8 @@ pub fn (expr Expr) is_blank_ident() bool {
|
||||||
|
|
||||||
pub fn (expr Expr) position() token.Position {
|
pub fn (expr Expr) position() token.Position {
|
||||||
// all uncommented have to be implemented
|
// all uncommented have to be implemented
|
||||||
match mut expr {
|
match expr {
|
||||||
|
// KEKW2
|
||||||
AnonFn {
|
AnonFn {
|
||||||
return expr.decl.pos
|
return expr.decl.pos
|
||||||
}
|
}
|
||||||
|
@ -1084,8 +1085,8 @@ pub fn (expr Expr) is_lvalue() bool {
|
||||||
|
|
||||||
pub fn (expr Expr) is_expr() bool {
|
pub fn (expr Expr) is_expr() bool {
|
||||||
match expr {
|
match expr {
|
||||||
IfExpr {return expr.is_expr}
|
IfExpr { return expr.is_expr }
|
||||||
MatchExpr {return expr.is_expr}
|
MatchExpr { return expr.is_expr }
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -1151,16 +1152,12 @@ pub fn (stmt Stmt) position() token.Position {
|
||||||
// field table.Field.default_expr, which should be ast.Expr
|
// field table.Field.default_expr, which should be ast.Expr
|
||||||
pub fn fe2ex(x table.FExpr) Expr {
|
pub fn fe2ex(x table.FExpr) Expr {
|
||||||
res := Expr{}
|
res := Expr{}
|
||||||
unsafe {
|
unsafe {C.memcpy(&res, &x, sizeof(Expr))}
|
||||||
C.memcpy(&res, &x, sizeof(Expr))
|
|
||||||
}
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ex2fe(x Expr) table.FExpr {
|
pub fn ex2fe(x Expr) table.FExpr {
|
||||||
res := table.FExpr{}
|
res := table.FExpr{}
|
||||||
unsafe {
|
unsafe {C.memcpy(&res, &x, sizeof(table.FExpr))}
|
||||||
C.memcpy(&res, &x, sizeof(table.FExpr))
|
|
||||||
}
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,7 @@ pub fn (s &Scope) find_with_scope(name string) ?(ScopeObject, &Scope) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (s &Scope) find(name string) ?ScopeObject {
|
pub fn (s &Scope) find(name string) ?ScopeObject {
|
||||||
for sc := s; true; sc = sc.parent
|
for sc := s; true; sc = sc.parent {
|
||||||
{
|
|
||||||
if name in sc.objects {
|
if name in sc.objects {
|
||||||
return sc.objects[name]
|
return sc.objects[name]
|
||||||
}
|
}
|
||||||
|
@ -85,6 +84,7 @@ pub fn (s &Scope) known_var(name string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut s Scope) update_var_type(name string, typ table.Type) {
|
pub fn (mut s Scope) update_var_type(name string, typ table.Type) {
|
||||||
|
s.end_pos = s.end_pos // TODO mut bug
|
||||||
match mut s.objects[name] {
|
match mut s.objects[name] {
|
||||||
Var {
|
Var {
|
||||||
if it.typ == typ {
|
if it.typ == typ {
|
||||||
|
|
104
vlib/v/ast/str.v
104
vlib/v/ast/str.v
|
@ -13,17 +13,12 @@ pub fn (node &FnDecl) modname() string {
|
||||||
}
|
}
|
||||||
mut pamod := node.name.all_before_last('.')
|
mut pamod := node.name.all_before_last('.')
|
||||||
if pamod == node.name.after('.') {
|
if pamod == node.name.after('.') {
|
||||||
pamod = if node.is_builtin {
|
pamod = if node.is_builtin { 'builtin' } else { 'main' }
|
||||||
'builtin'
|
|
||||||
} else {
|
|
||||||
'main'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return pamod
|
return pamod
|
||||||
}
|
}
|
||||||
|
|
||||||
// These methods are used only by vfmt, vdoc, and for debugging.
|
// These methods are used only by vfmt, vdoc, and for debugging.
|
||||||
|
|
||||||
pub fn (node &FnDecl) stringify(t &table.Table, cur_mod string) string {
|
pub fn (node &FnDecl) stringify(t &table.Table, cur_mod string) string {
|
||||||
mut f := strings.new_builder(30)
|
mut f := strings.new_builder(30)
|
||||||
if node.is_pub {
|
if node.is_pub {
|
||||||
|
@ -32,7 +27,7 @@ pub fn (node &FnDecl) stringify(t &table.Table, cur_mod string) string {
|
||||||
mut receiver := ''
|
mut receiver := ''
|
||||||
if node.is_method {
|
if node.is_method {
|
||||||
mut styp := util.no_cur_mod(t.type_to_str(node.receiver.typ), cur_mod)
|
mut styp := util.no_cur_mod(t.type_to_str(node.receiver.typ), cur_mod)
|
||||||
mut m := if node.rec_mut { node.receiver.typ.share().str() + ' ' } else { '' }
|
m := if node.rec_mut { node.receiver.typ.share().str() + ' ' } else { '' }
|
||||||
if node.rec_mut {
|
if node.rec_mut {
|
||||||
styp = styp[1..] // remove &
|
styp = styp[1..] // remove &
|
||||||
}
|
}
|
||||||
|
@ -51,11 +46,10 @@ pub fn (node &FnDecl) stringify(t &table.Table, cur_mod string) string {
|
||||||
mut name := if node.is_anon { '' } else { node.name.after('.') }
|
mut name := if node.is_anon { '' } else { node.name.after('.') }
|
||||||
if node.language == .c {
|
if node.language == .c {
|
||||||
name = 'C.$name'
|
name = 'C.$name'
|
||||||
}
|
} else if node.language == .js {
|
||||||
else if node.language == .js {
|
|
||||||
name = 'JS.$name'
|
name = 'JS.$name'
|
||||||
}
|
}
|
||||||
f.write('fn ${receiver}${name}')
|
f.write('fn $receiver$name')
|
||||||
if node.is_generic {
|
if node.is_generic {
|
||||||
f.write('<T>')
|
f.write('<T>')
|
||||||
}
|
}
|
||||||
|
@ -70,8 +64,8 @@ pub fn (node &FnDecl) stringify(t &table.Table, cur_mod string) string {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
is_last_arg := i == node.args.len - 1
|
is_last_arg := i == node.args.len - 1
|
||||||
should_add_type := is_last_arg || node.args[i + 1].typ != arg.typ || (node.is_variadic &&
|
should_add_type := is_last_arg || node.args[i + 1].typ != arg.typ ||
|
||||||
i == node.args.len - 2)
|
(node.is_variadic && i == node.args.len - 2)
|
||||||
if arg.is_mut {
|
if arg.is_mut {
|
||||||
f.write(arg.typ.share().str() + ' ')
|
f.write(arg.typ.share().str() + ' ')
|
||||||
}
|
}
|
||||||
|
@ -105,7 +99,7 @@ pub fn (node &FnDecl) stringify(t &table.Table, cur_mod string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (x &InfixExpr) str() string {
|
pub fn (x &InfixExpr) str() string {
|
||||||
return '${x.left.str()} $x.op.str() ${x.right.str()}'
|
return '$x.left.str() $x.op.str() $x.right.str()'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expressions in string interpolations may have to be put in braces if they
|
// Expressions in string interpolations may have to be put in braces if they
|
||||||
|
@ -116,14 +110,14 @@ pub fn (x &InfixExpr) str() string {
|
||||||
// This method creates the format specifier (including the colon) or an empty
|
// This method creates the format specifier (including the colon) or an empty
|
||||||
// string if none is needed and also returns (as bool) if the expression
|
// string if none is needed and also returns (as bool) if the expression
|
||||||
// must be enclosed in braces.
|
// must be enclosed in braces.
|
||||||
|
|
||||||
pub fn (lit &StringInterLiteral) get_fspec_braces(i int) (string, bool) {
|
pub fn (lit &StringInterLiteral) get_fspec_braces(i int) (string, bool) {
|
||||||
mut res := []string{}
|
mut res := []string{}
|
||||||
needs_fspec := lit.need_fmts[i] || lit.pluss[i] || (lit.fills[i] && lit.fwidths[i] >= 0) || lit.fwidths[i] != 0 || lit.precisions[i] != 0
|
needs_fspec := lit.need_fmts[i] || lit.pluss[i] ||
|
||||||
|
(lit.fills[i] && lit.fwidths[i] >= 0) || lit.fwidths[i] != 0 || lit.precisions[i] != 0
|
||||||
mut needs_braces := needs_fspec
|
mut needs_braces := needs_fspec
|
||||||
if !needs_braces {
|
if !needs_braces {
|
||||||
if i+1 < lit.vals.len && lit.vals[i+1].len > 0 {
|
if i + 1 < lit.vals.len && lit.vals[i + 1].len > 0 {
|
||||||
next_char := lit.vals[i+1][0]
|
next_char := lit.vals[i + 1][0]
|
||||||
if util.is_func_char(next_char) || next_char == `.` || next_char == `(` {
|
if util.is_func_char(next_char) || next_char == `.` || next_char == `(` {
|
||||||
needs_braces = true
|
needs_braces = true
|
||||||
}
|
}
|
||||||
|
@ -181,90 +175,94 @@ pub fn (lit &StringInterLiteral) get_fspec_braces(i int) (string, bool) {
|
||||||
pub fn (x Expr) str() string {
|
pub fn (x Expr) str() string {
|
||||||
match x {
|
match x {
|
||||||
BoolLiteral {
|
BoolLiteral {
|
||||||
return it.val.str()
|
return x.val.str()
|
||||||
}
|
}
|
||||||
CastExpr {
|
CastExpr {
|
||||||
return '${it.typname}(${it.expr.str()})'
|
return '${x.typname}($x.expr.str())'
|
||||||
}
|
}
|
||||||
CallExpr {
|
CallExpr {
|
||||||
sargs := args2str(it.args)
|
sargs := args2str(x.args)
|
||||||
if it.is_method {
|
if x.is_method {
|
||||||
return '${it.left.str()}.${it.name}($sargs)'
|
return '${x.left.str()}.${x.name}($sargs)'
|
||||||
}
|
}
|
||||||
return '${it.mod}.${it.name}($sargs)'
|
return '${x.mod}.${x.name}($sargs)'
|
||||||
}
|
}
|
||||||
CharLiteral {
|
CharLiteral {
|
||||||
return '`$it.val`'
|
return '`$x.val`'
|
||||||
}
|
}
|
||||||
EnumVal {
|
EnumVal {
|
||||||
return '.${it.val}'
|
return '.$x.val'
|
||||||
}
|
}
|
||||||
FloatLiteral {
|
FloatLiteral {
|
||||||
return it.val
|
return x.val
|
||||||
}
|
}
|
||||||
Ident {
|
Ident {
|
||||||
return it.name
|
return x.name
|
||||||
}
|
}
|
||||||
IndexExpr {
|
IndexExpr {
|
||||||
return '${it.left.str()}[${it.index.str()}]'
|
return '$x.left.str()[$x.index.str()]'
|
||||||
}
|
}
|
||||||
IntegerLiteral {
|
IntegerLiteral {
|
||||||
return it.val
|
return x.val
|
||||||
}
|
}
|
||||||
InfixExpr {
|
InfixExpr {
|
||||||
return '${it.left.str()} $it.op.str() ${it.right.str()}'
|
return '$x.left.str() $x.op.str() $x.right.str()'
|
||||||
}
|
}
|
||||||
ParExpr {
|
ParExpr {
|
||||||
return '($it.expr)'
|
return '($x.expr)'
|
||||||
}
|
}
|
||||||
PrefixExpr {
|
PrefixExpr {
|
||||||
return it.op.str() + it.right.str()
|
return x.op.str() + x.right.str()
|
||||||
}
|
}
|
||||||
RangeExpr {
|
RangeExpr {
|
||||||
mut s := '..'
|
mut s := '..'
|
||||||
if it.has_low {s = '$it.low ' + s}
|
if x.has_low {
|
||||||
if it.has_high {s = s + ' $it.high'}
|
s = '$x.low ' + s
|
||||||
|
}
|
||||||
|
if x.has_high {
|
||||||
|
s = s + ' $x.high'
|
||||||
|
}
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
SelectorExpr {
|
SelectorExpr {
|
||||||
return '${it.expr.str()}.${it.field_name}'
|
return '${x.expr.str()}.$x.field_name'
|
||||||
}
|
}
|
||||||
SizeOf {
|
SizeOf {
|
||||||
return 'sizeof($it.expr)'
|
return 'sizeof($x.expr)'
|
||||||
}
|
}
|
||||||
StringInterLiteral {
|
StringInterLiteral {
|
||||||
mut res := []string{}
|
mut res := []string{}
|
||||||
res << "'"
|
res << "'"
|
||||||
for i, val in it.vals {
|
for i, val in x.vals {
|
||||||
res << val
|
res << val
|
||||||
if i >= it.exprs.len {
|
if i >= x.exprs.len {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
res << '$'
|
res << '$'
|
||||||
fspec_str, needs_braces := it.get_fspec_braces(i)
|
fspec_str, needs_braces := x.get_fspec_braces(i)
|
||||||
if needs_braces {
|
if needs_braces {
|
||||||
res << '{'
|
res << '{'
|
||||||
res << it.exprs[i].str()
|
res << x.exprs[i].str()
|
||||||
res << fspec_str
|
res << fspec_str
|
||||||
res << '}'
|
res << '}'
|
||||||
} else {
|
} else {
|
||||||
res << it.exprs[i].str()
|
res << x.exprs[i].str()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res << "'"
|
res << "'"
|
||||||
return res.join('')
|
return res.join('')
|
||||||
}
|
}
|
||||||
StringLiteral {
|
StringLiteral {
|
||||||
return '"$it.val"'
|
return '"$x.val"'
|
||||||
}
|
}
|
||||||
TypeOf {
|
TypeOf {
|
||||||
return 'typeof(${it.expr.str()})'
|
return 'typeof($x.expr.str())'
|
||||||
}
|
}
|
||||||
Likely {
|
Likely {
|
||||||
return '_likely_(${it.expr.str()})'
|
return '_likely_($x.expr.str())'
|
||||||
}
|
}
|
||||||
UnsafeExpr {
|
UnsafeExpr {
|
||||||
return 'unsafe { $it.expr }'
|
return 'unsafe { $x.expr }'
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
|
@ -273,9 +271,9 @@ pub fn (x Expr) str() string {
|
||||||
|
|
||||||
pub fn (a CallArg) str() string {
|
pub fn (a CallArg) str() string {
|
||||||
if a.is_mut {
|
if a.is_mut {
|
||||||
return 'mut ${a.expr.str()}'
|
return 'mut $a.expr.str()'
|
||||||
}
|
}
|
||||||
return '${a.expr.str()}'
|
return '$a.expr.str()'
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn args2str(args []CallArg) string {
|
pub fn args2str(args []CallArg) string {
|
||||||
|
@ -290,7 +288,7 @@ pub fn (node Stmt) str() string {
|
||||||
match node {
|
match node {
|
||||||
AssignStmt {
|
AssignStmt {
|
||||||
mut out := ''
|
mut out := ''
|
||||||
for i, left in it.left {
|
for i, left in node.left {
|
||||||
if left is Ident {
|
if left is Ident {
|
||||||
var_info := left.var_info()
|
var_info := left.var_info()
|
||||||
if var_info.is_mut {
|
if var_info.is_mut {
|
||||||
|
@ -302,20 +300,20 @@ pub fn (node Stmt) str() string {
|
||||||
out += ','
|
out += ','
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out += ' $it.op.str() '
|
out += ' $node.op.str() '
|
||||||
for i, val in it.right {
|
for i, val in node.right {
|
||||||
out += val.str()
|
out += val.str()
|
||||||
if i < it.right.len - 1 {
|
if i < node.right.len - 1 {
|
||||||
out += ','
|
out += ','
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
ExprStmt {
|
ExprStmt {
|
||||||
return it.expr.str()
|
return node.expr.str()
|
||||||
}
|
}
|
||||||
FnDecl {
|
FnDecl {
|
||||||
return 'fn ${it.name}() { $it.stmts.len stmts }'
|
return 'fn ${node.name}() { $node.stmts.len stmts }'
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return '[unhandled stmt str type: ${typeof(node)} ]'
|
return '[unhandled stmt str type: ${typeof(node)} ]'
|
||||||
|
|
|
@ -96,10 +96,11 @@ pub fn (mut c Checker) check_scope_vars(sc &ast.Scope) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: fix all of these warnings
|
if obj.is_mut && !obj.is_changed && !c.is_builtin_mod && obj.name != 'it' {
|
||||||
// if obj.is_mut && !obj.is_changed {
|
// if obj.is_mut && !obj.is_changed && !c.is_builtin { //TODO C error bad field not checked
|
||||||
// c.warn('`$obj.name` is declared as mutable, but it was never changed', obj.pos)
|
// c.warn('`$obj.name` is declared as mutable, but it was never changed',
|
||||||
// }
|
// obj.pos)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
|
@ -555,7 +556,7 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||||
c.expected_type = former_expected_type
|
c.expected_type = former_expected_type
|
||||||
}
|
}
|
||||||
c.expected_type = table.void_type
|
c.expected_type = table.void_type
|
||||||
mut left_type := c.expr(infix_expr.left)
|
left_type := c.expr(infix_expr.left)
|
||||||
// left_type = c.unwrap_genric(c.expr(infix_expr.left))
|
// left_type = c.unwrap_genric(c.expr(infix_expr.left))
|
||||||
infix_expr.left_type = left_type
|
infix_expr.left_type = left_type
|
||||||
c.expected_type = left_type
|
c.expected_type = left_type
|
||||||
|
@ -816,6 +817,7 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns name and position of variable that needs write lock
|
// returns name and position of variable that needs write lock
|
||||||
|
// also sets `is_changed` to true (TODO update the name to reflect this?)
|
||||||
fn (mut c Checker) fail_if_immutable(expr ast.Expr) (string, token.Position) {
|
fn (mut c Checker) fail_if_immutable(expr ast.Expr) (string, token.Position) {
|
||||||
mut to_lock := '' // name of variable that needs lock
|
mut to_lock := '' // name of variable that needs lock
|
||||||
mut pos := token.Position{} // and its position
|
mut pos := token.Position{} // and its position
|
||||||
|
@ -1518,7 +1520,7 @@ pub fn (mut c Checker) check_expr_opt_call(expr ast.Expr, ret_type table.Type) t
|
||||||
return ret_type
|
return ret_type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut c Checker) check_or_expr(mut or_expr ast.OrExpr, ret_type table.Type) {
|
pub fn (mut c Checker) check_or_expr(or_expr ast.OrExpr, ret_type table.Type) {
|
||||||
if or_expr.kind == .propagate {
|
if or_expr.kind == .propagate {
|
||||||
if !c.cur_fn.return_type.has_flag(.optional) && c.cur_fn.name != 'main.main' {
|
if !c.cur_fn.return_type.has_flag(.optional) && c.cur_fn.name != 'main.main' {
|
||||||
c.error('to propagate the optional call, `$c.cur_fn.name` must itself return an optional',
|
c.error('to propagate the optional call, `$c.cur_fn.name` must itself return an optional',
|
||||||
|
@ -1536,7 +1538,7 @@ pub fn (mut c Checker) check_or_expr(mut or_expr ast.OrExpr, ret_type table.Type
|
||||||
// allow `f() or {}`
|
// allow `f() or {}`
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mut last_stmt := or_expr.stmts[stmts_len - 1]
|
last_stmt := or_expr.stmts[stmts_len - 1]
|
||||||
if ret_type != table.void_type {
|
if ret_type != table.void_type {
|
||||||
match mut last_stmt {
|
match mut last_stmt {
|
||||||
ast.ExprStmt {
|
ast.ExprStmt {
|
||||||
|
@ -2932,7 +2934,7 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) table.Type {
|
||||||
// since it is used in c.match_exprs() it saves checking twice
|
// since it is used in c.match_exprs() it saves checking twice
|
||||||
node.cond_type = cond_type
|
node.cond_type = cond_type
|
||||||
if cond_type == 0 {
|
if cond_type == 0 {
|
||||||
c.error('match 0 cond type', node.pos)
|
c.error('compiler bug: match 0 cond type', node.pos)
|
||||||
}
|
}
|
||||||
cond_type_sym := c.table.get_type_symbol(cond_type)
|
cond_type_sym := c.table.get_type_symbol(cond_type)
|
||||||
if cond_type_sym.kind !in [.sum_type, .interface_] {
|
if cond_type_sym.kind !in [.sum_type, .interface_] {
|
||||||
|
@ -2981,7 +2983,11 @@ pub fn (mut c Checker) match_expr(mut node ast.MatchExpr) table.Type {
|
||||||
// node.expected_type = c.expected_type
|
// node.expected_type = c.expected_type
|
||||||
// }
|
// }
|
||||||
node.return_type = ret_type
|
node.return_type = ret_type
|
||||||
// println('!m $expr_type')
|
if node.is_mut {
|
||||||
|
// Mark `x` in `match mut x {` as changed, and ensure it's mutable
|
||||||
|
// TODO2 enable when code is fixed
|
||||||
|
// c.fail_if_immutable(node.cond)
|
||||||
|
}
|
||||||
return ret_type
|
return ret_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -568,7 +568,7 @@ fn (p &Parser) fileis(s string) bool {
|
||||||
|
|
||||||
fn (mut p Parser) check_fn_mutable_arguments(typ table.Type, pos token.Position) {
|
fn (mut p Parser) check_fn_mutable_arguments(typ table.Type, pos token.Position) {
|
||||||
sym := p.table.get_type_symbol(typ)
|
sym := p.table.get_type_symbol(typ)
|
||||||
if sym.kind !in [.array, .struct_, .map, .placeholder] && !typ.is_ptr() {
|
if sym.kind !in [.array, .struct_, .map, .placeholder, .sum_type] && !typ.is_ptr() {
|
||||||
p.error_with_pos('mutable arguments are only allowed for arrays, maps, and structs\n' +
|
p.error_with_pos('mutable arguments are only allowed for arrays, maps, and structs\n' +
|
||||||
'return values instead: `fn foo(mut n $sym.name) {` => `fn foo(n $sym.name) $sym.name {`',
|
'return values instead: `fn foo(mut n $sym.name) {` => `fn foo(n $sym.name) $sym.name {`',
|
||||||
pos)
|
pos)
|
||||||
|
|
|
@ -229,6 +229,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
|
||||||
typ: typ.to_ptr()
|
typ: typ.to_ptr()
|
||||||
pos: cond_pos
|
pos: cond_pos
|
||||||
is_used: true
|
is_used: true
|
||||||
|
is_changed: true // TODO mut unchanged warning hack, remove
|
||||||
is_mut: is_mut
|
is_mut: is_mut
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ pub mut:
|
||||||
is_fmt bool // Used only for skipping ${} in strings, since we need literal
|
is_fmt bool // Used only for skipping ${} in strings, since we need literal
|
||||||
// string values when generating formatted code.
|
// string values when generating formatted code.
|
||||||
comments_mode CommentsMode
|
comments_mode CommentsMode
|
||||||
is_inside_toplvl_statement bool // *only* used in comments_mode: .toplevel_comments, toggled by parser
|
is_inside_toplvl_statement bool // *only* used in comments_mode: .toplevel_comments, toggled by parser
|
||||||
all_tokens []token.Token // *only* used in comments_mode: .toplevel_comments, contains all tokens
|
all_tokens []token.Token // *only* used in comments_mode: .toplevel_comments, contains all tokens
|
||||||
tidx int
|
tidx int
|
||||||
eofs int
|
eofs int
|
||||||
|
@ -178,8 +178,8 @@ fn (mut s Scanner) ident_name() string {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
// ident_fn_name look ahead and return name of function if possible, otherwise empty string
|
// ident_fn_name looks ahead and returns name of the function if possible, otherwise an empty string
|
||||||
fn (mut s Scanner) ident_fn_name() string {
|
fn (s &Scanner) ident_fn_name() string {
|
||||||
start := s.pos
|
start := s.pos
|
||||||
mut pos := s.pos
|
mut pos := s.pos
|
||||||
pos++
|
pos++
|
||||||
|
@ -221,9 +221,8 @@ fn (mut s Scanner) ident_fn_name() string {
|
||||||
if pos <= start || pos >= s.text.len {
|
if pos <= start || pos >= s.text.len {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
if s.text[start_pos].is_digit() || end_pos > s.text.len ||
|
if s.text[start_pos].is_digit() || end_pos > s.text.len || end_pos <= start_pos ||
|
||||||
end_pos <= start_pos || end_pos <= start ||
|
end_pos <= start || start_pos < start {
|
||||||
start_pos < start {
|
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
fn_name := s.text[start_pos..end_pos]
|
fn_name := s.text[start_pos..end_pos]
|
||||||
|
@ -231,7 +230,7 @@ fn (mut s Scanner) ident_fn_name() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ident_mod_name look ahead and return name of module this file belongs to if possible, otherwise empty string
|
// ident_mod_name look ahead and return name of module this file belongs to if possible, otherwise empty string
|
||||||
fn (mut s Scanner) ident_mod_name() string {
|
fn (s &Scanner) ident_mod_name() string {
|
||||||
start := s.pos
|
start := s.pos
|
||||||
mut pos := s.pos
|
mut pos := s.pos
|
||||||
pos++
|
pos++
|
||||||
|
@ -259,7 +258,7 @@ fn (mut s Scanner) ident_mod_name() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ident_struct_name look ahead and return name of last encountered struct if possible, otherwise empty string
|
// ident_struct_name look ahead and return name of last encountered struct if possible, otherwise empty string
|
||||||
fn (mut s Scanner) ident_struct_name() string {
|
fn (s &Scanner) ident_struct_name() string {
|
||||||
start := s.pos
|
start := s.pos
|
||||||
mut pos := s.pos
|
mut pos := s.pos
|
||||||
// Return last known stuct_name encountered to avoid using high order/anonymous function definitions
|
// Return last known stuct_name encountered to avoid using high order/anonymous function definitions
|
||||||
|
@ -303,9 +302,8 @@ fn (mut s Scanner) ident_struct_name() string {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
start_pos := pos + 1
|
start_pos := pos + 1
|
||||||
if s.text[start_pos].is_digit() || end_pos > s.text.len ||
|
if s.text[start_pos].is_digit() || end_pos > s.text.len || end_pos <= start_pos ||
|
||||||
end_pos <= start_pos || end_pos <= start ||
|
end_pos <= start || start_pos <= start {
|
||||||
start_pos <= start {
|
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
struct_name := s.text[start_pos..end_pos]
|
struct_name := s.text[start_pos..end_pos]
|
||||||
|
@ -354,8 +352,7 @@ fn (mut s Scanner) ident_bin_number() string {
|
||||||
}
|
}
|
||||||
if s.text[s.pos - 1] == num_sep {
|
if s.text[s.pos - 1] == num_sep {
|
||||||
s.error('cannot use `_` at the end of a numeric literal')
|
s.error('cannot use `_` at the end of a numeric literal')
|
||||||
}
|
} else if start_pos + 2 == s.pos {
|
||||||
else if start_pos + 2 == s.pos {
|
|
||||||
s.pos-- // adjust error position
|
s.pos-- // adjust error position
|
||||||
s.error('number part of this binary is not provided')
|
s.error('number part of this binary is not provided')
|
||||||
} else if has_wrong_digit {
|
} else if has_wrong_digit {
|
||||||
|
@ -394,8 +391,7 @@ fn (mut s Scanner) ident_hex_number() string {
|
||||||
}
|
}
|
||||||
if s.text[s.pos - 1] == num_sep {
|
if s.text[s.pos - 1] == num_sep {
|
||||||
s.error('cannot use `_` at the end of a numeric literal')
|
s.error('cannot use `_` at the end of a numeric literal')
|
||||||
}
|
} else if start_pos + 2 == s.pos {
|
||||||
else if start_pos + 2 == s.pos {
|
|
||||||
s.pos-- // adjust error position
|
s.pos-- // adjust error position
|
||||||
s.error('number part of this hexadecimal is not provided')
|
s.error('number part of this hexadecimal is not provided')
|
||||||
} else if has_wrong_digit {
|
} else if has_wrong_digit {
|
||||||
|
@ -434,8 +430,7 @@ fn (mut s Scanner) ident_oct_number() string {
|
||||||
}
|
}
|
||||||
if s.text[s.pos - 1] == num_sep {
|
if s.text[s.pos - 1] == num_sep {
|
||||||
s.error('cannot use `_` at the end of a numeric literal')
|
s.error('cannot use `_` at the end of a numeric literal')
|
||||||
}
|
} else if start_pos + 2 == s.pos {
|
||||||
else if start_pos + 2 == s.pos {
|
|
||||||
s.pos-- // adjust error position
|
s.pos-- // adjust error position
|
||||||
s.error('number part of this octal is not provided')
|
s.error('number part of this octal is not provided')
|
||||||
} else if has_wrong_digit {
|
} else if has_wrong_digit {
|
||||||
|
@ -455,7 +450,7 @@ fn (mut s Scanner) ident_dec_number() string {
|
||||||
// scan integer part
|
// scan integer part
|
||||||
for s.pos < s.text.len {
|
for s.pos < s.text.len {
|
||||||
c := s.text[s.pos]
|
c := s.text[s.pos]
|
||||||
if c == num_sep && s.text[s.pos + 1] == num_sep {
|
if c == num_sep && s.text[s.pos + 1] == num_sep {
|
||||||
s.error('cannot use `_` consecutively')
|
s.error('cannot use `_` consecutively')
|
||||||
}
|
}
|
||||||
if !c.is_digit() && c != num_sep {
|
if !c.is_digit() && c != num_sep {
|
||||||
|
@ -546,8 +541,7 @@ fn (mut s Scanner) ident_dec_number() string {
|
||||||
// error check: 5e
|
// error check: 5e
|
||||||
s.pos-- // adjust error position
|
s.pos-- // adjust error position
|
||||||
s.error('exponent has no digits')
|
s.error('exponent has no digits')
|
||||||
} else if s.pos < s.text.len &&
|
} else if s.pos < s.text.len && s.text[s.pos] == `.` && !is_range && !call_method {
|
||||||
s.text[s.pos] == `.` && !is_range && !call_method {
|
|
||||||
// error check: 1.23.4, 123.e+3.4
|
// error check: 1.23.4, 123.e+3.4
|
||||||
if has_exp {
|
if has_exp {
|
||||||
s.error('exponential part should be integer')
|
s.error('exponential part should be integer')
|
||||||
|
@ -608,7 +602,7 @@ pub fn (mut s Scanner) scan_all_tokens_in_buffer() {
|
||||||
cmode := s.comments_mode
|
cmode := s.comments_mode
|
||||||
s.comments_mode = .parse_comments
|
s.comments_mode = .parse_comments
|
||||||
for {
|
for {
|
||||||
mut t := s.text_scan()
|
t := s.text_scan()
|
||||||
s.all_tokens << t
|
s.all_tokens << t
|
||||||
if t.kind == .eof {
|
if t.kind == .eof {
|
||||||
break
|
break
|
||||||
|
@ -1093,7 +1087,7 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
start := s.pos + 1
|
start := s.pos + 1
|
||||||
s.ignore_line()
|
s.ignore_line()
|
||||||
mut comment_line_end := s.pos
|
mut comment_line_end := s.pos
|
||||||
if s.text[s.pos-1] == `\r` {
|
if s.text[s.pos - 1] == `\r` {
|
||||||
comment_line_end--
|
comment_line_end--
|
||||||
} else {
|
} else {
|
||||||
// fix line_nr, \n was read; the comment is marked on the next line
|
// fix line_nr, \n was read; the comment is marked on the next line
|
||||||
|
@ -1216,7 +1210,8 @@ fn (mut s Scanner) ident_string() string {
|
||||||
}
|
}
|
||||||
// Don't allow \0
|
// Don't allow \0
|
||||||
if c == `0` && s.pos > 2 && s.text[s.pos - 1] == slash {
|
if c == `0` && s.pos > 2 && s.text[s.pos - 1] == slash {
|
||||||
if (s.pos < s.text.len - 1 && s.text[s.pos + 1].is_digit()) || s.count_symbol_before(s.pos - 1, slash) % 2 == 0 {
|
if (s.pos < s.text.len - 1 && s.text[s.pos + 1].is_digit()) ||
|
||||||
|
s.count_symbol_before(s.pos - 1, slash) % 2 == 0 {
|
||||||
} else if !is_cstr && !is_raw {
|
} else if !is_cstr && !is_raw {
|
||||||
s.error(r'cannot use `\0` (NULL character) in the string literal')
|
s.error(r'cannot use `\0` (NULL character) in the string literal')
|
||||||
}
|
}
|
||||||
|
@ -1236,8 +1231,8 @@ fn (mut s Scanner) ident_string() string {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// $var
|
// $var
|
||||||
if prevc == `$` && util.is_name_char(c) && !is_raw &&
|
if prevc == `$` && util.is_name_char(c) && !is_raw && s.count_symbol_before(s.pos - 2, slash) %
|
||||||
s.count_symbol_before(s.pos - 2, slash) % 2 == 0 {
|
2 == 0 {
|
||||||
s.is_inside_string = true
|
s.is_inside_string = true
|
||||||
s.is_inter_start = true
|
s.is_inter_start = true
|
||||||
s.pos -= 2
|
s.pos -= 2
|
||||||
|
|
|
@ -13,7 +13,7 @@ const (
|
||||||
|
|
||||||
// compile_file compiles the content of a file by the given path as a template
|
// compile_file compiles the content of a file by the given path as a template
|
||||||
pub fn compile_file(path, fn_name string) string {
|
pub fn compile_file(path, fn_name string) string {
|
||||||
mut html := os.read_file(path) or {
|
html := os.read_file(path) or {
|
||||||
panic('html failed')
|
panic('html failed')
|
||||||
}
|
}
|
||||||
return compile_template(html, fn_name)
|
return compile_template(html, fn_name)
|
||||||
|
@ -82,7 +82,7 @@ _ = footer
|
||||||
pos := line.index('@include ') or {
|
pos := line.index('@include ') or {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
mut file_name := line[pos + 9..]
|
file_name := line[pos + 9..]
|
||||||
file_path := os.join_path('templates', '${file_name}.html')
|
file_path := os.join_path('templates', '${file_name}.html')
|
||||||
mut file_content := os.read_file(file_path) or {
|
mut file_content := os.read_file(file_path) or {
|
||||||
panic('reading file $file_name failed')
|
panic('reading file $file_name failed')
|
||||||
|
|
Loading…
Reference in New Issue