all: a massive merge of ast and table modules

pull/9554/head^2
Alexander Medvednikov 2021-04-02 01:57:09 +03:00
parent 043f6420f7
commit 7385f8e56b
88 changed files with 1839 additions and 1792 deletions

View File

@ -1,5 +1,12 @@
module main module main
import os
import log
import flag
import time
import vweb
import net.urllib
// This tool regenerates V's bootstrap .c files // This tool regenerates V's bootstrap .c files
// every time the V master branch is updated. // every time the V master branch is updated.
// if run with the --serve flag it will run in webhook // if run with the --serve flag it will run in webhook
@ -13,12 +20,6 @@ module main
// --log-file path to log file used when --log-to is 'file' // --log-file path to log file used when --log-to is 'file'
// --dry-run dont push anything to remote repo // --dry-run dont push anything to remote repo
// --force force update even if already up to date // --force force update even if already up to date
import os
import log
import flag
import time
import vweb
import net.urllib
// git credentials // git credentials
const ( const (

View File

@ -5,7 +5,7 @@ import net.urllib
import strings import strings
import markdown import markdown
import v.scanner import v.scanner
import v.table import v.ast
import v.token import v.token
import v.doc import v.doc
import v.pref import v.pref
@ -344,7 +344,7 @@ fn get_src_link(repo_url string, file_name string, line_nr int) string {
return url.str() return url.str()
} }
fn html_highlight(code string, tb &table.Table) string { fn html_highlight(code string, tb &ast.Table) string {
builtin := ['bool', 'string', 'i8', 'i16', 'int', 'i64', 'i128', 'byte', 'u16', 'u32', 'u64', builtin := ['bool', 'string', 'i8', 'i16', 'int', 'i64', 'i128', 'byte', 'u16', 'u32', 'u64',
'u128', 'rune', 'f32', 'f64', 'int_literal', 'float_literal', 'byteptr', 'voidptr', 'any'] 'u128', 'rune', 'f32', 'f64', 'int_literal', 'float_literal', 'byteptr', 'voidptr', 'any']
highlight_code := fn (tok token.Token, typ HighlightTokenTyp) string { highlight_code := fn (tok token.Token, typ HighlightTokenTyp) string {
@ -425,7 +425,7 @@ fn html_highlight(code string, tb &table.Table) string {
return buf.str() return buf.str()
} }
fn doc_node_html(dn doc.DocNode, link string, head bool, include_examples bool, tb &table.Table) string { fn doc_node_html(dn doc.DocNode, link string, head bool, include_examples bool, tb &ast.Table) string {
mut dnw := strings.new_builder(200) mut dnw := strings.new_builder(200)
head_tag := if head { 'h1' } else { 'h2' } head_tag := if head { 'h1' } else { 'h2' }
comments := dn.merge_comments_without_examples() comments := dn.merge_comments_without_examples()

View File

@ -3,7 +3,7 @@ module main
import os import os
import v.doc import v.doc
import term import term
import v.table import v.ast
import v.scanner import v.scanner
import v.token import v.token
import strings import strings
@ -137,7 +137,7 @@ fn gen_footer_text(d &doc.Doc, include_timestamp bool) string {
return '$footer_text Generated on: $time_str' return '$footer_text Generated on: $time_str'
} }
fn color_highlight(code string, tb &table.Table) string { fn color_highlight(code string, tb &ast.Table) string {
builtin := ['bool', 'string', 'i8', 'i16', 'int', 'i64', 'i128', 'byte', 'u16', 'u32', 'u64', builtin := ['bool', 'string', 'i8', 'i16', 'int', 'i64', 'i128', 'byte', 'u16', 'u32', 'u64',
'u128', 'rune', 'f32', 'f64', 'int_literal', 'float_literal', 'byteptr', 'voidptr', 'any'] 'u128', 'rune', 'f32', 'f64', 'int_literal', 'float_literal', 'byteptr', 'voidptr', 'any']
highlight_code := fn (tok token.Token, typ HighlightTokenTyp) string { highlight_code := fn (tok token.Token, typ HighlightTokenTyp) string {

View File

@ -12,7 +12,6 @@ import v.pref
import v.fmt import v.fmt
import v.util import v.util
import v.parser import v.parser
import v.table
import vhelp import vhelp
struct FormatOptions { struct FormatOptions {
@ -156,7 +155,7 @@ fn (foptions &FormatOptions) format_file(file string) {
if foptions.is_verbose { if foptions.is_verbose {
eprintln('vfmt2 running fmt.fmt over file: $file') eprintln('vfmt2 running fmt.fmt over file: $file')
} }
table := table.new_table() table := ast.new_table()
// checker := checker.new_checker(table, prefs) // checker := checker.new_checker(table, prefs)
file_ast := parser.parse_file(file, table, .parse_comments, prefs, &ast.Scope{ file_ast := parser.parse_file(file, table, .parse_comments, prefs, &ast.Scope{
parent: 0 parent: 0
@ -180,7 +179,7 @@ fn (foptions &FormatOptions) format_pipe() {
eprintln('vfmt2 running fmt.fmt over stdin') eprintln('vfmt2 running fmt.fmt over stdin')
} }
input_text := os.get_raw_lines_joined() input_text := os.get_raw_lines_joined()
table := table.new_table() table := ast.new_table()
// checker := checker.new_checker(table, prefs) // checker := checker.new_checker(table, prefs)
file_ast := parser.parse_text(input_text, '', table, .parse_comments, prefs, &ast.Scope{ file_ast := parser.parse_text(input_text, '', table, .parse_comments, prefs, &ast.Scope{
parent: 0 parent: 0

View File

@ -28,6 +28,7 @@ const (
'vlib/v/tests/generics_return_generics_struct_test.v', /* generic fn param removed */ 'vlib/v/tests/generics_return_generics_struct_test.v', /* generic fn param removed */
'vlib/v/tests/interop_test.v', /* bad comment formatting */ 'vlib/v/tests/interop_test.v', /* bad comment formatting */
'vlib/v/tests/generics_test.v', /* some silent error */ 'vlib/v/tests/generics_test.v', /* some silent error */
'vlib/v/gen/js/tests/js.v', /* local `hello` fn, gets replaced with module `hello` aliased as `hl` */
] ]
vfmt_verify_list = [ vfmt_verify_list = [
'cmd/', 'cmd/',
@ -55,7 +56,7 @@ const (
'vlib/v/eval/', 'vlib/v/eval/',
'vlib/v/fmt/', 'vlib/v/fmt/',
'vlib/v/gen/c/', 'vlib/v/gen/c/',
//'vlib/v/gen/js/', 'vlib/v/gen/js/',
'vlib/v/gen/x64/', 'vlib/v/gen/x64/',
'vlib/v/live/', 'vlib/v/live/',
'vlib/v/markused/', 'vlib/v/markused/',
@ -64,7 +65,6 @@ const (
'vlib/v/pref/', 'vlib/v/pref/',
'vlib/v/preludes', 'vlib/v/preludes',
'vlib/v/scanner/', 'vlib/v/scanner/',
'vlib/v/table/',
'vlib/v/tests/', 'vlib/v/tests/',
'vlib/v/token/', 'vlib/v/token/',
'vlib/v/util/', 'vlib/v/util/',

View File

@ -3,7 +3,6 @@ import flag
import term import term
import time import time
import v.parser import v.parser
import v.table
import v.ast import v.ast
import v.pref import v.pref
@ -34,7 +33,7 @@ mut:
cut_index int // the cut position in the source from context.path cut_index int // the cut position in the source from context.path
max_index int // the maximum index (equivalent to the file content length) max_index int // the maximum index (equivalent to the file content length)
// parser context in the worker processes: // parser context in the worker processes:
table table.Table table ast.Table
scope ast.Scope scope ast.Scope
pref &pref.Preferences pref &pref.Preferences
period_ms int // print periodic progress period_ms int // print periodic progress
@ -48,7 +47,7 @@ fn main() {
context.log('> worker ${pid:5} starts parsing at cut_index: ${context.cut_index:5} | $context.path') context.log('> worker ${pid:5} starts parsing at cut_index: ${context.cut_index:5} | $context.path')
// A worker's process job is to try to parse a single given file in context.path. // A worker's process job is to try to parse a single given file in context.path.
// It can crash/panic freely. // It can crash/panic freely.
context.table = table.new_table() context.table = ast.new_table()
context.scope = &ast.Scope{ context.scope = &ast.Scope{
parent: 0 parent: 0
} }

View File

@ -7,8 +7,8 @@ import os.cmdline
import v.vet import v.vet
import v.pref import v.pref
import v.parser import v.parser
import v.table
import v.token import v.token
import v.ast
import term import term
struct Vet { struct Vet {
@ -94,7 +94,7 @@ fn (mut vt Vet) vet_file(path string) {
vt.file = path vt.file = path
mut prefs := pref.new_preferences() mut prefs := pref.new_preferences()
prefs.is_vet = true prefs.is_vet = true
table := table.new_table() table := ast.new_table()
vt.vprintln("vetting file '$path'...") vt.vprintln("vetting file '$path'...")
_, errors := parser.parse_vet_file(path, table, prefs) _, errors := parser.parse_vet_file(path, table, prefs)
// Transfer errors from scanner and parser // Transfer errors from scanner and parser

View File

@ -25,9 +25,9 @@ or `Preferences.compile_defines_all` **if any file is defined**.
## Parsing files ## Parsing files
To parse something a new template is created as the first step: To parse something a new template is created as the first step:
```v ```v
import v.table import v.ast
table := table.new_table() table := ast.new_table()
``` ```
a new preference is created: a new preference is created:

View File

@ -4,7 +4,6 @@
module ast module ast
import v.token import v.token
import v.table
import v.errors import v.errors
import v.pref import v.pref
@ -16,7 +15,7 @@ pub type Expr = AnonFn | ArrayDecompose | ArrayInit | AsCast | Assoc | AtExpr |
Ident | IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr | Ident | IfExpr | IfGuardExpr | IndexExpr | InfixExpr | IntegerLiteral | Likely | LockExpr |
MapInit | MatchExpr | NodeError | None | OffsetOf | OrExpr | ParExpr | PostfixExpr | MapInit | MatchExpr | NodeError | None | OffsetOf | OrExpr | ParExpr | PostfixExpr |
PrefixExpr | RangeExpr | SelectExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral | PrefixExpr | RangeExpr | SelectExpr | SelectorExpr | SizeOf | SqlExpr | StringInterLiteral |
StringLiteral | StructInit | Type | TypeOf | UnsafeExpr StringLiteral | StructInit | TypeNode | TypeOf | UnsafeExpr
pub type Stmt = AsmStmt | AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDecl | pub type Stmt = AsmStmt | AssertStmt | AssignStmt | Block | BranchStmt | CompFor | ConstDecl |
DeferStmt | EmptyStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt | DeferStmt | EmptyStmt | EnumDecl | ExprStmt | FnDecl | ForCStmt | ForInStmt | ForStmt |
@ -27,14 +26,14 @@ pub type Stmt = AsmStmt | AssertStmt | AssignStmt | Block | BranchStmt | CompFor
// the .position() token.Position methods too. // the .position() token.Position methods too.
pub type ScopeObject = AsmRegister | ConstField | GlobalField | Var pub type ScopeObject = AsmRegister | ConstField | GlobalField | Var
// TODO: replace table.Param // TODO: replace Param
pub type Node = CallArg | ConstField | EnumField | Expr | Field | File | GlobalField | pub type Node = CallArg | ConstField | EmptyNode | EnumField | Expr | File | GlobalField |
IfBranch | MatchBranch | NodeError | ScopeObject | SelectBranch | Stmt | StructField | IfBranch | MatchBranch | NodeError | Param | ScopeObject | SelectBranch | Stmt | StructField |
StructInitField | table.Param StructInitField
pub struct Type { pub struct TypeNode {
pub: pub:
typ table.Type typ Type
pos token.Position pos token.Position
} }
@ -55,6 +54,14 @@ pub fn empty_stmt() Stmt {
return EmptyStmt{} return EmptyStmt{}
} }
pub struct EmptyNode {
x int
}
pub fn empty_node() Node {
return EmptyNode{}
}
// `{stmts}` or `unsafe {stmts}` // `{stmts}` or `unsafe {stmts}`
pub struct Block { pub struct Block {
pub: pub:
@ -72,7 +79,7 @@ pub:
comments []Comment comments []Comment
is_expr bool is_expr bool
pub mut: pub mut:
typ table.Type typ Type
} }
pub struct IntegerLiteral { pub struct IntegerLiteral {
@ -91,7 +98,7 @@ pub struct StringLiteral {
pub: pub:
val string val string
is_raw bool is_raw bool
language table.Language language Language
pos token.Position pos token.Position
} }
@ -107,7 +114,7 @@ pub:
fmt_poss []token.Position fmt_poss []token.Position
pos token.Position pos token.Position
pub mut: pub mut:
expr_types []table.Type expr_types []Type
fmts []byte fmts []byte
need_fmts []bool // an explicit non-default fmt required, e.g. `x` need_fmts []bool // an explicit non-default fmt required, e.g. `x`
} }
@ -133,12 +140,12 @@ pub:
mut_pos token.Position mut_pos token.Position
next_token token.Kind next_token token.Kind
pub mut: pub mut:
expr Expr // expr.field_name expr Expr // expr.field_name
expr_type table.Type // type of `Foo` in `Foo.bar` expr_type Type // type of `Foo` in `Foo.bar`
typ table.Type // type of the entire thing (`Foo.bar`) typ Type // type of the entire thing (`Foo.bar`)
name_type table.Type // T in `T.name` or typeof in `typeof(expr).name` name_type Type // T in `T.name` or typeof in `typeof(expr).name`
scope &Scope scope &Scope
from_embed_type table.Type // holds the type of the embed that the method is called from from_embed_type Type // holds the type of the embed that the method is called from
} }
// root_ident returns the origin ident where the selector started. // root_ident returns the origin ident where the selector started.
@ -157,7 +164,7 @@ pub struct Module {
pub: pub:
name string // encoding.base64 name string // encoding.base64
short_name string // base64 short_name string // base64
attrs []table.Attr attrs []Attr
pos token.Position pos token.Position
name_pos token.Position // `name` in import name name_pos token.Position // `name` in import name
is_skipped bool // module main can be skipped in single file programs is_skipped bool // module main can be skipped in single file programs
@ -170,20 +177,26 @@ pub:
comments []Comment comments []Comment
default_expr Expr default_expr Expr
has_default_expr bool has_default_expr bool
attrs []table.Attr attrs []Attr
is_public bool is_pub bool
default_val string
is_mut bool
is_global bool
pub mut: pub mut:
name string default_expr_typ Type
typ table.Type name string
typ Type
} }
/*
pub struct Field { pub struct Field {
pub: pub:
name string name string
pos token.Position pos token.Position
pub mut: pub mut:
typ table.Type typ Type
} }
*/
// const field in const declaration group // const field in const declaration group
pub struct ConstField { pub struct ConstField {
@ -194,8 +207,8 @@ pub:
is_pub bool is_pub bool
pos token.Position pos token.Position
pub mut: pub mut:
typ table.Type // the type of the const field, it can be any type in V typ Type // the type of the const field, it can be any type in V
comments []Comment // comments before current const field comments []Comment // comments before current const field
} }
// const declaration // const declaration
@ -213,7 +226,7 @@ pub struct StructDecl {
pub: pub:
pos token.Position pos token.Position
name string name string
gen_types []table.Type gen_types []Type
is_pub bool is_pub bool
// _pos fields for vfmt // _pos fields for vfmt
mut_pos int // mut: mut_pos int // mut:
@ -221,9 +234,9 @@ pub:
pub_mut_pos int // pub mut: pub_mut_pos int // pub mut:
global_pos int // __global: global_pos int // __global:
module_pos int // module: module_pos int // module:
language table.Language language Language
is_union bool is_union bool
attrs []table.Attr attrs []Attr
end_comments []Comment end_comments []Comment
embeds []Embed embeds []Embed
pub mut: pub mut:
@ -232,14 +245,14 @@ pub mut:
pub struct Embed { pub struct Embed {
pub: pub:
typ table.Type typ Type
pos token.Position pos token.Position
} }
pub struct StructEmbedding { pub struct StructEmbedding {
pub: pub:
name string name string
typ table.Type typ Type
pos token.Position pos token.Position
} }
@ -264,8 +277,8 @@ pub:
next_comments []Comment next_comments []Comment
pub mut: pub mut:
name string name string
typ table.Type typ Type
expected_type table.Type expected_type Type
} }
pub struct StructInitEmbed { pub struct StructInitEmbed {
@ -276,8 +289,8 @@ pub:
next_comments []Comment next_comments []Comment
pub mut: pub mut:
name string name string
typ table.Type typ Type
expected_type table.Type expected_type Type
} }
pub struct StructInit { pub struct StructInit {
@ -288,9 +301,9 @@ pub:
pub mut: pub mut:
unresolved bool unresolved bool
pre_comments []Comment pre_comments []Comment
typ table.Type typ Type
update_expr Expr update_expr Expr
update_expr_type table.Type update_expr_type Type
update_expr_comments []Comment update_expr_comments []Comment
has_update_expr bool has_update_expr bool
fields []StructInitField fields []StructInitField
@ -323,8 +336,8 @@ pub:
pub struct AnonFn { pub struct AnonFn {
pub mut: pub mut:
decl FnDecl decl FnDecl
typ table.Type // the type of anonymous fn. Both .typ and .decl.name are auto generated typ Type // the type of anonymous fn. Both .typ and .decl.name are auto generated
has_gen bool // has been generated has_gen bool // has been generated
} }
// function or method declaration // function or method declaration
@ -332,23 +345,23 @@ pub struct FnDecl {
pub: pub:
name string name string
mod string mod string
params []table.Param params []Param
is_deprecated bool is_deprecated bool
is_pub bool is_pub bool
is_variadic bool is_variadic bool
is_anon bool is_anon bool
is_manualfree bool // true, when [manualfree] is used on a fn is_manualfree bool // true, when [manualfree] is used on a fn
is_main bool // true for `fn main()` is_main bool // true for `fn main()`
is_test bool // true for `fn test_abcde` is_test bool // true for `fn test_abcde`
is_conditional bool // true for `[if abc] fn abc(){}` is_conditional bool // true for `[if abc] fn abc(){}`
receiver Field receiver StructField // TODO this is not a struct field
receiver_pos token.Position // `(u User)` in `fn (u User) name()` position receiver_pos token.Position // `(u User)` in `fn (u User) name()` position
is_method bool is_method bool
method_type_pos token.Position // `User` in ` fn (u User)` position method_type_pos token.Position // `User` in ` fn (u User)` position
method_idx int method_idx int
rec_mut bool // is receiver mutable rec_mut bool // is receiver mutable
rec_share table.ShareType rec_share ShareType
language table.Language language Language
no_body bool // just a definition `fn C.malloc()` no_body bool // just a definition `fn C.malloc()`
is_builtin bool // this function is defined in builtin/strconv is_builtin bool // this function is defined in builtin/strconv
pos token.Position // function declaration position pos token.Position // function declaration position
@ -356,12 +369,12 @@ pub:
file string file string
generic_params []GenericParam generic_params []GenericParam
is_direct_arr bool // direct array access is_direct_arr bool // direct array access
attrs []table.Attr attrs []Attr
skip_gen bool // this function doesn't need to be generated (for example [if foo]) skip_gen bool // this function doesn't need to be generated (for example [if foo])
pub mut: pub mut:
stmts []Stmt stmts []Stmt
defer_stmts []DeferStmt defer_stmts []DeferStmt
return_type table.Type return_type Type
has_return bool has_return bool
comments []Comment // comments *after* the header, but *before* `{`; used for InterfaceDecl comments []Comment // comments *after* the header, but *before* `{`; used for InterfaceDecl
next_comments []Comment // coments that are one line after the decl; used for InterfaceDecl next_comments []Comment // coments that are one line after the decl; used for InterfaceDecl
@ -394,19 +407,19 @@ pub mut:
is_method bool is_method bool
is_field bool // temp hack, remove ASAP when re-impl CallExpr / Selector (joe) is_field bool // temp hack, remove ASAP when re-impl CallExpr / Selector (joe)
args []CallArg args []CallArg
expected_arg_types []table.Type expected_arg_types []Type
language table.Language language Language
or_block OrExpr or_block OrExpr
left Expr // `user` in `user.register()` left Expr // `user` in `user.register()`
left_type table.Type // type of `user` left_type Type // type of `user`
receiver_type table.Type // User receiver_type Type // User
return_type table.Type return_type Type
should_be_skipped bool should_be_skipped bool
generic_types []table.Type generic_types []Type
generic_list_pos token.Position generic_list_pos token.Position
free_receiver bool // true if the receiver expression needs to be freed free_receiver bool // true if the receiver expression needs to be freed
scope &Scope scope &Scope
from_embed_type table.Type // holds the type of the embed that the method is called from from_embed_type Type // holds the type of the embed that the method is called from
comments []Comment comments []Comment
} }
@ -420,11 +433,11 @@ pub struct AutofreeArgVar {
pub struct CallArg { pub struct CallArg {
pub: pub:
is_mut bool is_mut bool
share table.ShareType share ShareType
expr Expr expr Expr
comments []Comment comments []Comment
pub mut: pub mut:
typ table.Type typ Type
is_tmp_autofree bool // this tells cgen that a tmp variable has to be used for the arg expression in order to free it after the call is_tmp_autofree bool // this tells cgen that a tmp variable has to be used for the arg expression in order to free it after the call
pos token.Position pos token.Position
// tmp_name string // for autofree // tmp_name string // for autofree
@ -437,7 +450,7 @@ pub:
exprs []Expr exprs []Expr
comments []Comment comments []Comment
pub mut: pub mut:
types []table.Type types []Type
} }
/* /*
@ -457,15 +470,15 @@ pub struct Var {
pub: pub:
name string name string
expr Expr expr Expr
share table.ShareType share ShareType
is_mut bool is_mut bool
is_autofree_tmp bool is_autofree_tmp bool
is_arg bool // fn args should not be autofreed is_arg bool // fn args should not be autofreed
is_auto_deref bool is_auto_deref bool
pub mut: pub mut:
typ table.Type typ Type
orig_type table.Type // original sumtype type; 0 if it's not a sumtype orig_type Type // original sumtype type; 0 if it's not a sumtype
sum_type_casts []table.Type // nested sum types require nested smart casting, for that a list of types is needed sum_type_casts []Type // nested sum types require nested smart casting, for that a list of types is needed
// TODO: move this to a real docs site later // TODO: move this to a real docs site later
// 10 <- original type (orig_type) // 10 <- original type (orig_type)
// [11, 12, 13] <- cast order (sum_type_casts) // [11, 12, 13] <- cast order (sum_type_casts)
@ -483,12 +496,12 @@ pub mut:
// struct fields change type in scopes // struct fields change type in scopes
pub struct ScopeStructField { pub struct ScopeStructField {
pub: pub:
struct_type table.Type // type of struct struct_type Type // type of struct
name string name string
pos token.Position pos token.Position
typ table.Type typ Type
sum_type_casts []table.Type // nested sum types require nested smart casting, for that a list of types is needed sum_type_casts []Type // nested sum types require nested smart casting, for that a list of types is needed
orig_type table.Type // original sumtype type; 0 if it's not a sumtype orig_type Type // original sumtype type; 0 if it's not a sumtype
// TODO: move this to a real docs site later // TODO: move this to a real docs site later
// 10 <- original type (orig_type) // 10 <- original type (orig_type)
// [11, 12, 13] <- cast order (sum_type_casts) // [11, 12, 13] <- cast order (sum_type_casts)
@ -502,7 +515,7 @@ pub:
has_expr bool has_expr bool
pos token.Position pos token.Position
pub mut: pub mut:
typ table.Type typ Type
comments []Comment comments []Comment
} }
@ -520,8 +533,8 @@ pub:
apath string // absolute path during compilation to the resource apath string // absolute path during compilation to the resource
} }
// Each V source file is represented by one ast.File structure. // Each V source file is represented by one File structure.
// When the V compiler runs, the parser will fill an []ast.File. // When the V compiler runs, the parser will fill an []File.
// That array is then passed to V's checker. // That array is then passed to V's checker.
pub struct File { pub struct File {
pub: pub:
@ -545,18 +558,18 @@ pub mut:
pub struct IdentFn { pub struct IdentFn {
pub mut: pub mut:
typ table.Type typ Type
} }
// TODO: (joe) remove completely, use ident.obj // TODO: (joe) remove completely, use ident.obj
// instead which points to the scope object // instead which points to the scope object
pub struct IdentVar { pub struct IdentVar {
pub mut: pub mut:
typ table.Type typ Type
is_mut bool is_mut bool
is_static bool is_static bool
is_optional bool is_optional bool
share table.ShareType share ShareType
} }
pub type IdentInfo = IdentFn | IdentVar pub type IdentInfo = IdentFn | IdentVar
@ -573,7 +586,7 @@ pub enum IdentKind {
// A single identifier // A single identifier
pub struct Ident { pub struct Ident {
pub: pub:
language table.Language language Language
tok_kind token.Kind tok_kind token.Kind
pos token.Position pos token.Position
mut_pos token.Position mut_pos token.Position
@ -609,8 +622,8 @@ pub:
pub mut: pub mut:
left Expr left Expr
right Expr right Expr
left_type table.Type left_type Type
right_type table.Type right_type Type
auto_locked string auto_locked string
or_block OrExpr or_block OrExpr
} }
@ -631,7 +644,7 @@ pub:
op token.Kind op token.Kind
pos token.Position pos token.Position
pub mut: pub mut:
right_type table.Type right_type Type
right Expr right Expr
or_block OrExpr or_block OrExpr
is_option bool // IfGuard is_option bool // IfGuard
@ -644,7 +657,7 @@ pub:
or_expr OrExpr or_expr OrExpr
pub mut: pub mut:
left Expr left Expr
left_type table.Type // array, map, fixed array left_type Type // array, map, fixed array
is_setter bool is_setter bool
is_map bool is_map bool
is_array bool is_array bool
@ -662,7 +675,7 @@ pub:
pub mut: pub mut:
branches []IfBranch // includes all `else if` branches branches []IfBranch // includes all `else if` branches
is_expr bool is_expr bool
typ table.Type typ Type
has_else bool has_else bool
} }
@ -692,7 +705,7 @@ pub:
pub mut: pub mut:
lockeds []Ident // `x`, `y` in `lock x, y {` lockeds []Ident // `x`, `y` in `lock x, y {`
is_expr bool is_expr bool
typ table.Type typ Type
} }
pub struct MatchExpr { pub struct MatchExpr {
@ -704,9 +717,9 @@ pub:
comments []Comment // comments before the first branch comments []Comment // comments before the first branch
pub mut: pub mut:
is_expr bool // returns a value is_expr bool // returns a value
return_type table.Type return_type Type
cond_type table.Type // type of `x` in `match x {` cond_type Type // type of `x` in `match x {`
expected_type table.Type // for debugging only expected_type Type // for debugging only
is_sum_type bool is_sum_type bool
} }
@ -728,8 +741,8 @@ pub:
pos token.Position pos token.Position
has_exception bool has_exception bool
pub mut: pub mut:
is_expr bool // returns a value is_expr bool // returns a value
expected_type table.Type // for debugging only expected_type Type // for debugging only
} }
pub struct SelectBranch { pub struct SelectBranch {
@ -757,7 +770,7 @@ pub:
typ_pos token.Position typ_pos token.Position
pub mut: pub mut:
// expr Expr // expr Expr
typ table.Type typ Type
} }
pub struct ForStmt { pub struct ForStmt {
@ -783,11 +796,11 @@ pub:
val_is_mut bool // `for mut val in vals {` means that modifying `val` will modify the array val_is_mut bool // `for mut val in vals {` means that modifying `val` will modify the array
// and the array cannot be indexed inside the loop // and the array cannot be indexed inside the loop
pub mut: pub mut:
key_type table.Type key_type Type
val_type table.Type val_type Type
cond_type table.Type cond_type Type
kind table.Kind // array/map/string kind Kind // array/map/string
label string // `label: for {` label string // `label: for {`
scope &Scope scope &Scope
} }
@ -837,8 +850,8 @@ pub:
pub mut: pub mut:
right []Expr right []Expr
left []Expr left []Expr
left_types []table.Type left_types []Type
right_types []table.Type right_types []Type
is_static bool // for translated code only is_static bool // for translated code only
is_simple bool // `x+=2` in `for x:=1; ; x+=2` is_simple bool // `x+=2` in `for x:=1; ; x+=2`
has_cross_var bool has_cross_var bool
@ -847,10 +860,10 @@ pub mut:
pub struct AsCast { pub struct AsCast {
pub: pub:
expr Expr expr Expr
typ table.Type typ Type
pos token.Position pos token.Position
pub mut: pub mut:
expr_type table.Type expr_type Type
} }
// an enum value, like OS.macos or .macos // an enum value, like OS.macos or .macos
@ -861,7 +874,7 @@ pub:
mod string // for full path `mod_Enum_val` mod string // for full path `mod_Enum_val`
pos token.Position pos token.Position
pub mut: pub mut:
typ table.Type typ Type
} }
// enum field in enum declaration // enum field in enum declaration
@ -880,11 +893,11 @@ pub struct EnumDecl {
pub: pub:
name string name string
is_pub bool is_pub bool
is_flag bool // true when the enum has [flag] tag,for bit field enum is_flag bool // true when the enum has [flag] tag,for bit field enum
is_multi_allowed bool // true when the enum has [_allow_multiple_values] tag is_multi_allowed bool // true when the enum has [_allow_multiple_values] tag
comments []Comment // comments before the first EnumField comments []Comment // comments before the first EnumField
fields []EnumField // all the enum fields fields []EnumField // all the enum fields
attrs []table.Attr // attributes of enum declaration attrs []Attr // attributes of enum declaration
pos token.Position pos token.Position
} }
@ -892,7 +905,7 @@ pub struct AliasTypeDecl {
pub: pub:
name string name string
is_pub bool is_pub bool
parent_type table.Type parent_type Type
pos token.Position pos token.Position
comments []Comment comments []Comment
} }
@ -904,14 +917,14 @@ pub:
is_pub bool is_pub bool
pos token.Position pos token.Position
comments []Comment comments []Comment
typ table.Type typ Type
pub mut: pub mut:
variants []SumTypeVariant variants []SumTypeVariant
} }
pub struct SumTypeVariant { pub struct SumTypeVariant {
pub: pub:
typ table.Type typ Type
pos token.Position pos token.Position
} }
@ -919,7 +932,7 @@ pub struct FnTypeDecl {
pub: pub:
name string name string
is_pub bool is_pub bool
typ table.Type typ Type
pos token.Position pos token.Position
comments []Comment comments []Comment
} }
@ -956,7 +969,7 @@ pub:
pub mut: pub mut:
go_stmt GoStmt go_stmt GoStmt
mut: mut:
return_type table.Type return_type Type
} }
pub struct GotoLabel { pub struct GotoLabel {
@ -988,9 +1001,9 @@ pub:
has_cap bool has_cap bool
has_default bool has_default bool
pub mut: pub mut:
expr_types []table.Type // [Dog, Cat] // also used for interface_types expr_types []Type // [Dog, Cat] // also used for interface_types
elem_type table.Type // element type elem_type Type // element type
typ table.Type // array type typ Type // array type
} }
pub struct ArrayDecompose { pub struct ArrayDecompose {
@ -998,8 +1011,8 @@ pub:
expr Expr expr Expr
pos token.Position pos token.Position
pub mut: pub mut:
expr_type table.Type expr_type Type
arg_type table.Type arg_type Type
} }
pub struct ChanInit { pub struct ChanInit {
@ -1008,8 +1021,8 @@ pub:
cap_expr Expr cap_expr Expr
has_cap bool has_cap bool
pub mut: pub mut:
typ table.Type typ Type
elem_type table.Type elem_type Type
} }
pub struct MapInit { pub struct MapInit {
@ -1020,9 +1033,9 @@ pub:
comments [][]Comment // comments after key-value pairs comments [][]Comment // comments after key-value pairs
pre_cmnts []Comment // comments before the first key-value pair pre_cmnts []Comment // comments before the first key-value pair
pub mut: pub mut:
typ table.Type typ Type
key_type table.Type key_type Type
value_type table.Type value_type Type
} }
// s[10..20] // s[10..20]
@ -1035,9 +1048,9 @@ pub:
pos token.Position pos token.Position
} }
// NB: &string(x) gets parsed as ast.PrefixExpr{ right: ast.CastExpr{...} } // NB: &string(x) gets parsed as PrefixExpr{ right: CastExpr{...} }
// TODO: that is very likely a parsing bug. It should get parsed as just // TODO: that is very likely a parsing bug. It should get parsed as just
// ast.CastExpr{...}, where .typname is '&string' instead. // CastExpr{...}, where .typname is '&string' instead.
// The current situation leads to special cases in vfmt and cgen // The current situation leads to special cases in vfmt and cgen
// (see prefix_expr_cast_expr in fmt.v, and .is_amp in cgen.v) // (see prefix_expr_cast_expr in fmt.v, and .is_amp in cgen.v)
// .in_prexpr is also needed because of that, because the checker needs to // .in_prexpr is also needed because of that, because the checker needs to
@ -1045,15 +1058,15 @@ pub:
// `string(x,y)`, while skipping the real pointer casts like `&string(x)`. // `string(x,y)`, while skipping the real pointer casts like `&string(x)`.
pub struct CastExpr { pub struct CastExpr {
pub: pub:
expr Expr // `buf` in `string(buf, n)` expr Expr // `buf` in `string(buf, n)`
arg Expr // `n` in `string(buf, n)` arg Expr // `n` in `string(buf, n)`
typ table.Type // `string` TODO rename to `type_to_cast_to` typ Type // `string` TODO rename to `type_to_cast_to`
pos token.Position pos token.Position
pub mut: pub mut:
typname string // TypeSymbol.name typname string // TypeSymbol.name
expr_type table.Type // `byteptr` expr_type Type // `byteptr`
has_arg bool has_arg bool
in_prexpr bool // is the parent node an ast.PrefixExpr in_prexpr bool // is the parent node an PrefixExpr
} }
pub struct AsmStmt { pub struct AsmStmt {
@ -1091,7 +1104,7 @@ pub struct AsmRegister {
pub: pub:
name string // eax or r12d name string // eax or r12d
mut: mut:
typ table.Type typ Type
size int size int
} }
@ -1143,7 +1156,7 @@ pub:
constraint string // '=r' constraint string // '=r'
expr Expr // (a) expr Expr // (a)
comments []Comment // // this is a comment comments []Comment // // this is a comment
typ table.Type typ Type
pos token.Position pos token.Position
} }
@ -1243,7 +1256,7 @@ pub:
pos token.Position pos token.Position
pub mut: pub mut:
expr Expr expr Expr
expr_type table.Type expr_type Type
} }
pub enum OrKind { pub enum OrKind {
@ -1279,7 +1292,7 @@ pub:
exprs []Expr exprs []Expr
pos token.Position pos token.Position
pub mut: pub mut:
typ table.Type typ Type
scope &Scope scope &Scope
} }
@ -1289,12 +1302,12 @@ pub:
expr Expr // checker uses this to set typ expr Expr // checker uses this to set typ
pos token.Position pos token.Position
pub mut: pub mut:
typ table.Type typ Type
} }
pub struct OffsetOf { pub struct OffsetOf {
pub: pub:
struct_type table.Type struct_type Type
field string field string
pos token.Position pos token.Position
} }
@ -1311,7 +1324,7 @@ pub:
expr Expr expr Expr
pos token.Position pos token.Position
pub mut: pub mut:
expr_type table.Type expr_type Type
} }
pub struct DumpExpr { pub struct DumpExpr {
@ -1319,7 +1332,7 @@ pub:
expr Expr expr Expr
pos token.Position pos token.Position
pub mut: pub mut:
expr_type table.Type expr_type Type
cname string // filled in the checker cname string // filled in the checker
} }
@ -1336,7 +1349,7 @@ pub:
vals []Expr vals []Expr
pos token.Position pos token.Position
pub mut: pub mut:
return_type table.Type return_type Type
} }
// @FN, @STRUCT, @MOD etc. See full list in token.valid_at_tokens // @FN, @STRUCT, @MOD etc. See full list in token.valid_at_tokens
@ -1356,8 +1369,8 @@ pub:
field_expr Expr field_expr Expr
pos token.Position pos token.Position
pub mut: pub mut:
left_type table.Type left_type Type
typ table.Type typ Type
} }
pub struct ComptimeCall { pub struct ComptimeCall {
@ -1379,8 +1392,8 @@ pub:
is_env bool is_env bool
env_pos token.Position env_pos token.Position
pub mut: pub mut:
sym table.TypeSymbol sym TypeSymbol
result_type table.Type result_type Type
env_value string env_value string
args []CallArg args []CallArg
} }
@ -1407,14 +1420,14 @@ pub:
updated_columns []string // for `update set x=y` updated_columns []string // for `update set x=y`
update_exprs []Expr // for `update` update_exprs []Expr // for `update`
pub mut: pub mut:
table_expr Type table_expr TypeNode
fields []table.Field fields []StructField
sub_structs map[int]SqlStmt sub_structs map[int]SqlStmt
} }
pub struct SqlExpr { pub struct SqlExpr {
pub: pub:
typ table.Type typ Type
is_count bool is_count bool
db_expr Expr // `db` in `sql db {` db_expr Expr // `db` in `sql db {`
has_where bool has_where bool
@ -1429,14 +1442,14 @@ pub:
limit_expr Expr limit_expr Expr
pub mut: pub mut:
where_expr Expr where_expr Expr
table_expr Type table_expr TypeNode
fields []table.Field fields []StructField
sub_structs map[int]SqlExpr sub_structs map[int]SqlExpr
} }
pub struct NodeError { pub struct NodeError {
pub: pub:
idx int // index for referencing the related ast.File error idx int // index for referencing the related File error
pos token.Position pos token.Position
} }
@ -1462,8 +1475,8 @@ pub fn (expr Expr) position() token.Position {
ChanInit, CharLiteral, ConcatExpr, Comment, ComptimeCall, ComptimeSelector, EnumVal, DumpExpr, ChanInit, CharLiteral, ConcatExpr, Comment, ComptimeCall, ComptimeSelector, EnumVal, DumpExpr,
FloatLiteral, GoExpr, Ident, IfExpr, IndexExpr, IntegerLiteral, Likely, LockExpr, MapInit, FloatLiteral, GoExpr, Ident, IfExpr, IndexExpr, IntegerLiteral, Likely, LockExpr, MapInit,
MatchExpr, None, OffsetOf, OrExpr, ParExpr, PostfixExpr, PrefixExpr, RangeExpr, SelectExpr, MatchExpr, None, OffsetOf, OrExpr, ParExpr, PostfixExpr, PrefixExpr, RangeExpr, SelectExpr,
SelectorExpr, SizeOf, SqlExpr, StringInterLiteral, StringLiteral, StructInit, Type, TypeOf, SelectorExpr, SizeOf, SqlExpr, StringInterLiteral, StringLiteral, StructInit, TypeNode,
UnsafeExpr { TypeOf, UnsafeExpr {
return expr.pos return expr.pos
} }
IfGuardExpr { IfGuardExpr {
@ -1559,10 +1572,10 @@ pub fn (stmt Stmt) check_c_expr() ? {
// CTempVar is used in cgen only, to hold nodes for temporary variables // CTempVar is used in cgen only, to hold nodes for temporary variables
pub struct CTempVar { pub struct CTempVar {
pub: pub:
name string // the name of the C temporary variable; used by g.expr(x) name string // the name of the C temporary variable; used by g.expr(x)
orig Expr // the original expression, which produced the C temp variable; used by x.str() orig Expr // the original expression, which produced the C temp variable; used by x.str()
typ table.Type // the type of the original expression typ Type // the type of the original expression
is_ptr bool // whether the type is a pointer is_ptr bool // whether the type is a pointer
} }
pub fn (node Node) position() token.Position { pub fn (node Node) position() token.Position {
@ -1570,6 +1583,9 @@ pub fn (node Node) position() token.Position {
NodeError { NodeError {
return token.Position{} return token.Position{}
} }
EmptyNode {
return token.Position{}
}
Stmt { Stmt {
mut pos := node.pos mut pos := node.pos
if node is Import { if node is Import {
@ -1585,8 +1601,7 @@ pub fn (node Node) position() token.Position {
StructField { StructField {
return node.pos.extend(node.type_pos) return node.pos.extend(node.type_pos)
} }
MatchBranch, SelectBranch, Field, EnumField, ConstField, StructInitField, GlobalField, MatchBranch, SelectBranch, EnumField, ConstField, StructInitField, GlobalField, Param {
table.Param {
return node.pos return node.pos
} }
IfBranch { IfBranch {
@ -1760,27 +1775,6 @@ pub fn (node Node) children() []Node {
return children return children
} }
// TODO: remove this fugly hack :-|
// fe2ex/1 and ex2fe/1 are used to convert back and forth from
// table.FExpr to ast.Expr , which in turn is needed to break
// a dependency cycle between v.ast and v.table, for the single
// field table.Field.default_expr, which should be ast.Expr
pub fn fe2ex(x table.FExpr) Expr {
unsafe {
res := Expr{}
C.memcpy(&res, &x, sizeof(Expr))
return res
}
}
pub fn ex2fe(x Expr) table.FExpr {
unsafe {
res := table.FExpr{}
C.memcpy(&res, &x, sizeof(table.FExpr))
return res
}
}
// helper for dealing with `m[k1][k2][k3][k3] = value` // helper for dealing with `m[k1][k2][k3][k3] = value`
pub fn (mut lx IndexExpr) recursive_mapset_is_setter(val bool) { pub fn (mut lx IndexExpr) recursive_mapset_is_setter(val bool) {
lx.is_setter = val lx.is_setter = val
@ -1792,7 +1786,7 @@ pub fn (mut lx IndexExpr) recursive_mapset_is_setter(val bool) {
} }
// return all the registers for a give architecture // return all the registers for a give architecture
pub fn all_registers(mut t table.Table, arch pref.Arch) map[string]ScopeObject { pub fn all_registers(mut t Table, arch pref.Arch) map[string]ScopeObject {
mut res := map[string]ScopeObject{} mut res := map[string]ScopeObject{}
match arch { match arch {
.amd64, .i386 { .amd64, .i386 {
@ -1809,7 +1803,7 @@ pub fn all_registers(mut t table.Table, arch pref.Arch) map[string]ScopeObject {
for name, max_num in array { for name, max_num in array {
for i in 0 .. max_num { for i in 0 .. max_num {
hash_index := name.index('#') or { hash_index := name.index('#') or {
panic('ast.all_registers: no hashtag found') panic('all_registers: no hashtag found')
} }
assembled_name := '${name[..hash_index]}$i${name[hash_index + 1..]}' assembled_name := '${name[..hash_index]}$i${name[hash_index + 1..]}'
res[assembled_name] = AsmRegister{ res[assembled_name] = AsmRegister{
@ -1850,7 +1844,7 @@ pub fn all_registers(mut t table.Table, arch pref.Arch) map[string]ScopeObject {
} }
} }
else { // TODO else { // TODO
panic('ast.all_registers: unhandled arch') panic('all_registers: unhandled arch')
} }
} }
@ -1858,7 +1852,7 @@ pub fn all_registers(mut t table.Table, arch pref.Arch) map[string]ScopeObject {
} }
// only for arm and riscv because x86 has different sized registers // only for arm and riscv because x86 has different sized registers
fn gen_all_registers(mut t table.Table, without_numbers []string, with_numbers map[string]int, bit_size int) map[string]ScopeObject { fn gen_all_registers(mut t Table, without_numbers []string, with_numbers map[string]int, bit_size int) map[string]ScopeObject {
mut res := map[string]ScopeObject{} mut res := map[string]ScopeObject{}
for name in without_numbers { for name in without_numbers {
res[name] = AsmRegister{ res[name] = AsmRegister{
@ -1869,7 +1863,7 @@ fn gen_all_registers(mut t table.Table, without_numbers []string, with_numbers m
} }
for name, max_num in with_numbers { for name, max_num in with_numbers {
for i in 0 .. max_num { for i in 0 .. max_num {
hash_index := name.index('#') or { panic('ast.all_registers: no hashtag found') } hash_index := name.index('#') or { panic('all_registers: no hashtag found') }
assembled_name := '${name[..hash_index]}$i${name[hash_index + 1..]}' assembled_name := '${name[..hash_index]}$i${name[hash_index + 1..]}'
res[assembled_name] = AsmRegister{ res[assembled_name] = AsmRegister{
name: assembled_name name: assembled_name

View File

@ -1,7 +1,7 @@
// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module table module ast
import v.token import v.token

View File

@ -1,13 +1,13 @@
// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module table module ast
import v.cflag import v.cflag
// check if cflag is in table // check if cflag is in table
fn (mytable &Table) has_cflag(flag cflag.CFlag) bool { fn (t &Table) has_cflag(flag cflag.CFlag) bool {
for cf in mytable.cflags { for cf in t.cflags {
if cf.os == flag.os && cf.name == flag.name && cf.value == flag.value { if cf.os == flag.os && cf.name == flag.name && cf.value == flag.value {
return true return true
} }
@ -15,9 +15,9 @@ fn (mytable &Table) has_cflag(flag cflag.CFlag) bool {
return false return false
} }
// parse the flags to (table.cflags) []CFlag // parse the flags to (ast.cflags) []CFlag
// Note: clean up big time (joe-c) // Note: clean up big time (joe-c)
pub fn (mut mytable Table) parse_cflag(cflg string, mod string, ctimedefines []string) ?bool { pub fn (mut t Table) parse_cflag(cflg string, mod string, ctimedefines []string) ?bool {
allowed_flags := ['framework', 'library', 'Wa', 'Wl', 'Wp', 'I', 'l', 'L'] allowed_flags := ['framework', 'library', 'Wa', 'Wl', 'Wp', 'I', 'l', 'L']
flag_orig := cflg.trim_space() flag_orig := cflg.trim_space()
mut flag := flag_orig mut flag := flag_orig
@ -78,8 +78,8 @@ pub fn (mut mytable Table) parse_cflag(cflg string, mod string, ctimedefines []s
name: name name: name
value: value value: value
} }
if !mytable.has_cflag(cf) { if !t.has_cflag(cf) {
mytable.cflags << cf t.cflags << cf
} }
if index == -1 { if index == -1 {
break break

View File

@ -1,4 +1,4 @@
import v.table import v.ast
import v.cflag import v.cflag
const ( const (
@ -10,7 +10,7 @@ const (
) )
fn test_parse_valid_cflags() { fn test_parse_valid_cflags() {
mut t := table.new_table() mut t := ast.new_table()
expected_flags := [ expected_flags := [
make_flag('freebsd', '-I', '/usr/local/include/freetype2'), make_flag('freebsd', '-I', '/usr/local/include/freetype2'),
make_flag('linux', '-l', 'glfw'), make_flag('linux', '-l', 'glfw'),
@ -36,7 +36,7 @@ fn test_parse_valid_cflags() {
} }
fn test_parse_invalid_cflags() { fn test_parse_invalid_cflags() {
mut t := table.new_table() mut t := ast.new_table()
// -I, -L, -l must have values // -I, -L, -l must have values
assert_parse_invalid_flag(mut t, 'windows -l') assert_parse_invalid_flag(mut t, 'windows -l')
assert_parse_invalid_flag(mut t, '-I') assert_parse_invalid_flag(mut t, '-I')
@ -53,11 +53,11 @@ fn test_parse_invalid_cflags() {
assert t.cflags.len == 0 assert t.cflags.len == 0
} }
fn parse_valid_flag(mut t table.Table, flag string) { fn parse_valid_flag(mut t ast.Table, flag string) {
t.parse_cflag(flag, module_name, cdefines) or {} t.parse_cflag(flag, module_name, cdefines) or {}
} }
fn assert_parse_invalid_flag(mut t table.Table, flag string) { fn assert_parse_invalid_flag(mut t ast.Table, flag string) {
t.parse_cflag(flag, module_name, cdefines) or { return } t.parse_cflag(flag, module_name, cdefines) or { return }
assert false assert false
} }

View File

@ -1,11 +1,11 @@
module ast module ast
import v.table import v.ast
pub fn resolve_init(node StructInit, typ table.Type, t &table.Table) Expr { pub fn resolve_init(node StructInit, typ Type, t &Table) Expr {
type_sym := t.get_type_symbol(typ) type_sym := t.get_type_symbol(typ)
if type_sym.kind == .array { if type_sym.kind == .array {
array_info := type_sym.info as table.Array array_info := type_sym.info as Array
mut has_len := false mut has_len := false
mut has_cap := false mut has_cap := false
mut has_default := false mut has_default := false
@ -32,7 +32,7 @@ pub fn resolve_init(node StructInit, typ table.Type, t &table.Table) Expr {
} }
} }
} }
return ArrayInit{ return ast.ArrayInit{
// TODO: mod is not being set for now, we could need this in future // TODO: mod is not being set for now, we could need this in future
// mod: mod // mod: mod
pos: node.pos pos: node.pos
@ -47,16 +47,16 @@ pub fn resolve_init(node StructInit, typ table.Type, t &table.Table) Expr {
exprs: exprs exprs: exprs
} }
} else if type_sym.kind == .map { } else if type_sym.kind == .map {
map_info := type_sym.info as table.Map map_info := type_sym.info as Map
mut keys := []Expr{} mut keys := []Expr{}
mut vals := []Expr{} mut vals := []Expr{}
for field in node.fields { for field in node.fields {
keys << StringLiteral{ keys << ast.StringLiteral{
val: field.name val: field.name
} }
vals << field.expr vals << field.expr
} }
return MapInit{ return ast.MapInit{
typ: typ typ: typ
key_type: map_info.key_type key_type: map_info.key_type
value_type: map_info.value_type value_type: map_info.value_type
@ -65,7 +65,7 @@ pub fn resolve_init(node StructInit, typ table.Type, t &table.Table) Expr {
} }
} }
// struct / other (sumtype?) // struct / other (sumtype?)
return StructInit{ return ast.StructInit{
...node ...node
unresolved: false unresolved: false
} }

View File

@ -3,7 +3,7 @@
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module ast module ast
import v.table import v.ast
pub struct Scope { pub struct Scope {
pub mut: pub mut:
@ -18,7 +18,7 @@ pub mut:
} }
pub fn new_scope(parent &Scope, start_pos int) &Scope { pub fn new_scope(parent &Scope, start_pos int) &Scope {
return &Scope{ return &ast.Scope{
parent: parent parent: parent
start_pos: start_pos start_pos: start_pos
} }
@ -54,7 +54,7 @@ pub fn (s &Scope) find(name string) ?ScopeObject {
return none return none
} }
pub fn (s &Scope) find_struct_field(struct_type table.Type, field_name string) ?ScopeStructField { pub fn (s &Scope) find_struct_field(struct_type Type, field_name string) ?ScopeStructField {
for sc := s; true; sc = sc.parent { for sc := s; true; sc = sc.parent {
for field in sc.struct_fields { for field in sc.struct_fields {
if field.struct_type == struct_type && field.name == field_name { if field.struct_type == struct_type && field.name == field_name {
@ -103,7 +103,7 @@ pub fn (s &Scope) known_var(name string) bool {
return false return false
} }
pub fn (mut s Scope) update_var_type(name string, typ table.Type) { pub fn (mut s Scope) update_var_type(name string, typ Type) {
s.end_pos = s.end_pos // TODO mut bug s.end_pos = s.end_pos // TODO mut bug
mut obj := s.objects[name] mut obj := s.objects[name]
match mut obj { match mut obj {

View File

@ -3,7 +3,7 @@
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module ast module ast
import v.table import v.ast
import v.util import v.util
import strings import strings
@ -19,7 +19,7 @@ pub fn (node &FnDecl) modname() string {
} }
// 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, m2a map[string]string) string { pub fn (node &FnDecl) stringify(t &Table, cur_mod string, m2a map[string]string) string {
mut f := strings.new_builder(30) mut f := strings.new_builder(30)
if node.is_pub { if node.is_pub {
f.write_string('pub ') f.write_string('pub ')
@ -117,7 +117,7 @@ pub fn (node &FnDecl) stringify(t &table.Table, cur_mod string, m2a map[string]s
} }
} }
f.write_string(')') f.write_string(')')
if node.return_type != table.void_type { if node.return_type != ast.void_type {
mut rs := util.no_cur_mod(t.type_to_str(node.return_type), cur_mod) mut rs := util.no_cur_mod(t.type_to_str(node.return_type), cur_mod)
for mod, alias in m2a { for mod, alias in m2a {
rs = rs.replace(mod, alias) rs = rs.replace(mod, alias)
@ -351,8 +351,8 @@ pub fn (x Expr) str() string {
StringLiteral { StringLiteral {
return "'$x.val'" return "'$x.val'"
} }
Type { TypeNode {
return 'Type($x.typ)' return 'TypeNode($x.typ)'
} }
TypeOf { TypeOf {
return 'typeof($x.expr.str())' return 'typeof($x.expr.str())'

View File

@ -1,7 +1,7 @@
// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved. // Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved.
// Use of this source code is governed by an MIT license // Use of this source code is governed by an MIT license
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module table module ast
import v.cflag import v.cflag
import v.token import v.token
@ -18,7 +18,7 @@ pub mut:
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
cmod_prefix string // needed for table.type_to_str(Type) while vfmt; contains `os.` cmod_prefix string // needed for ast.type_to_str(Type) while vfmt; contains `os.`
is_fmt bool is_fmt bool
used_fns map[string]bool // filled in by the checker, when pref.skip_unused = true; used_fns map[string]bool // filled in by the checker, when pref.skip_unused = true;
used_consts map[string]bool // filled in by the checker, when pref.skip_unused = true; used_consts map[string]bool // filled in by the checker, when pref.skip_unused = true;
@ -82,6 +82,7 @@ fn (p []Param) equals(o []Param) bool {
return true return true
} }
/*
pub struct Var { pub struct Var {
pub: pub:
name string name string
@ -89,6 +90,7 @@ pub:
mut: mut:
typ Type typ Type
} }
*/
pub fn new_table() &Table { pub fn new_table() &Table {
mut t := &Table{ mut t := &Table{
@ -240,14 +242,14 @@ pub fn (t &Table) type_find_method(s &TypeSymbol, name string) ?Fn {
return none return none
} }
fn (t &Table) register_aggregate_field(mut sym TypeSymbol, name string) ?Field { fn (t &Table) register_aggregate_field(mut sym TypeSymbol, name string) ?StructField {
if sym.kind != .aggregate { if sym.kind != .aggregate {
panic('Unexpected type symbol: $sym.kind') panic('Unexpected type symbol: $sym.kind')
} }
mut agg_info := sym.info as Aggregate mut agg_info := sym.info as Aggregate
// an aggregate always has at least 2 types // an aggregate always has at least 2 types
mut found_once := false mut found_once := false
mut new_field := Field{ mut new_field := StructField{
// default_expr: ast.empty_expr() // default_expr: ast.empty_expr()
} }
for typ in agg_info.types { for typ in agg_info.types {
@ -276,7 +278,7 @@ pub fn (t &Table) struct_has_field(s &TypeSymbol, name string) bool {
} }
// search from current type up through each parent looking for field // search from current type up through each parent looking for field
pub fn (t &Table) find_field(s &TypeSymbol, name string) ?Field { pub fn (t &Table) find_field(s &TypeSymbol, name string) ?StructField {
// println('find_field($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx') // println('find_field($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx')
mut ts := s mut ts := s
for { for {
@ -316,13 +318,13 @@ pub fn (t &Table) find_field(s &TypeSymbol, name string) ?Field {
} }
// search for a given field, looking through embedded fields // search for a given field, looking through embedded fields
pub fn (t &Table) find_field_with_embeds(sym &TypeSymbol, field_name string) ?Field { pub fn (t &Table) find_field_with_embeds(sym &TypeSymbol, field_name string) ?StructField {
if f := t.find_field(sym, field_name) { if f := t.find_field(sym, field_name) {
return f return f
} else { } else {
// look for embedded field // look for embedded field
if sym.info is Struct { if sym.info is Struct {
mut found_fields := []Field{} mut found_fields := []StructField{}
mut embed_of_found_fields := []Type{} mut embed_of_found_fields := []Type{}
for embed in sym.info.embeds { for embed in sym.info.embeds {
embed_sym := t.get_type_symbol(embed) embed_sym := t.get_type_symbol(embed)
@ -347,7 +349,7 @@ pub fn (t &Table) resolve_common_sumtype_fields(sym_ &TypeSymbol) {
if info.found_fields { if info.found_fields {
return return
} }
mut field_map := map[string]Field{} mut field_map := map[string]StructField{}
mut field_usages := map[string]int{} mut field_usages := map[string]int{}
for variant in info.variants { for variant in info.variants {
mut v_sym := t.get_type_symbol(variant) mut v_sym := t.get_type_symbol(variant)
@ -360,7 +362,7 @@ pub fn (t &Table) resolve_common_sumtype_fields(sym_ &TypeSymbol) {
v_sym.info.fields v_sym.info.fields
} }
else { else {
[]Field{} []StructField{}
} }
} }
for field in fields { for field in fields {
@ -867,8 +869,8 @@ pub fn (mut t Table) register_fn_gen_type(fn_name string, types []Type) {
// TODO: there is a bug when casting sumtype the other way if its pointer // TODO: there is a bug when casting sumtype the other way if its pointer
// so until fixed at least show v (not C) error `x(variant) = y(SumType*)` // so until fixed at least show v (not C) error `x(variant) = y(SumType*)`
pub fn (mytable &Table) sumtype_has_variant(parent Type, variant Type) bool { pub fn (t &Table) sumtype_has_variant(parent Type, variant Type) bool {
parent_sym := mytable.get_type_symbol(parent) parent_sym := t.get_type_symbol(parent)
if parent_sym.kind == .sum_type { if parent_sym.kind == .sum_type {
parent_info := parent_sym.info as SumType parent_info := parent_sym.info as SumType
for v in parent_info.variants { for v in parent_info.variants {
@ -894,11 +896,11 @@ pub fn (t &Table) known_type_names() []string {
// has_deep_child_no_ref returns true if type is struct and has any child or nested child with the type of the given name // has_deep_child_no_ref returns true if type is struct and has any child or nested child with the type of the given name
// the given name consists of module and name (`mod.Name`) // the given name consists of module and name (`mod.Name`)
// it doesn't care about childs that are references // it doesn't care about childs that are references
pub fn (mytable &Table) has_deep_child_no_ref(ts &TypeSymbol, name string) bool { pub fn (t &Table) has_deep_child_no_ref(ts &TypeSymbol, name string) bool {
if ts.info is Struct { if ts.info is Struct {
for field in ts.info.fields { for field in ts.info.fields {
sym := mytable.get_type_symbol(field.typ) sym := t.get_type_symbol(field.typ)
if !field.typ.is_ptr() && (sym.name == name || mytable.has_deep_child_no_ref(sym, name)) { if !field.typ.is_ptr() && (sym.name == name || t.has_deep_child_no_ref(sym, name)) {
return true return true
} }
} }

View File

@ -9,7 +9,7 @@
// flag: (int(type)>>24) & 0xff // flag: (int(type)>>24) & 0xff
// nr_muls: (int(type)>>16) & 0xff // nr_muls: (int(type)>>16) & 0xff
// idx: u16(type) & 0xffff // idx: u16(type) & 0xffff
module table module ast
import strings import strings
import v.pref import v.pref
@ -109,10 +109,10 @@ pub fn (t ShareType) str() string {
pub fn (t Type) atomic_typename() string { pub fn (t Type) atomic_typename() string {
idx := t.idx() idx := t.idx()
match idx { match idx {
table.u32_type_idx { return 'atomic_uint' } ast.u32_type_idx { return 'atomic_uint' }
table.int_type_idx { return 'atomic_int' } ast.int_type_idx { return 'atomic_int' }
table.u64_type_idx { return 'atomic_ullong' } ast.u64_type_idx { return 'atomic_ullong' }
table.i64_type_idx { return 'atomic_llong' } ast.i64_type_idx { return 'atomic_llong' }
else { return 'unknown_atomic' } else { return 'unknown_atomic' }
} }
} }
@ -133,12 +133,12 @@ pub fn (t Type) idx() int {
[inline] [inline]
pub fn (t Type) is_void() bool { pub fn (t Type) is_void() bool {
return t == table.void_type return t == ast.void_type
} }
[inline] [inline]
pub fn (t Type) is_full() bool { pub fn (t Type) is_full() bool {
return t != 0 && t != table.void_type return t != 0 && t != ast.void_type
} }
// return nr_muls for `t` // return nr_muls for `t`
@ -273,42 +273,42 @@ pub fn new_type_ptr(idx int, nr_muls int) Type {
// built in pointers (voidptr, byteptr, charptr) // built in pointers (voidptr, byteptr, charptr)
[inline] [inline]
pub fn (typ Type) is_pointer() bool { pub fn (typ Type) is_pointer() bool {
return typ.idx() in table.pointer_type_idxs return typ.idx() in ast.pointer_type_idxs
} }
[inline] [inline]
pub fn (typ Type) is_float() bool { pub fn (typ Type) is_float() bool {
return typ.idx() in table.float_type_idxs return typ.idx() in ast.float_type_idxs
} }
[inline] [inline]
pub fn (typ Type) is_int() bool { pub fn (typ Type) is_int() bool {
return typ.idx() in table.integer_type_idxs return typ.idx() in ast.integer_type_idxs
} }
[inline] [inline]
pub fn (typ Type) is_signed() bool { pub fn (typ Type) is_signed() bool {
return typ.idx() in table.signed_integer_type_idxs return typ.idx() in ast.signed_integer_type_idxs
} }
[inline] [inline]
pub fn (typ Type) is_unsigned() bool { pub fn (typ Type) is_unsigned() bool {
return typ.idx() in table.unsigned_integer_type_idxs return typ.idx() in ast.unsigned_integer_type_idxs
} }
[inline] [inline]
pub fn (typ Type) is_int_literal() bool { pub fn (typ Type) is_int_literal() bool {
return typ.idx() == table.int_literal_type_idx return typ.idx() == ast.int_literal_type_idx
} }
[inline] [inline]
pub fn (typ Type) is_number() bool { pub fn (typ Type) is_number() bool {
return typ.idx() in table.number_type_idxs return typ.idx() in ast.number_type_idxs
} }
[inline] [inline]
pub fn (typ Type) is_string() bool { pub fn (typ Type) is_string() bool {
return typ.idx() in table.string_type_idxs return typ.idx() in ast.string_type_idxs
} }
pub const ( pub const (
@ -408,11 +408,11 @@ pub:
} }
// returns TypeSymbol kind only if there are no type modifiers // returns TypeSymbol kind only if there are no type modifiers
pub fn (table &Table) type_kind(typ Type) Kind { pub fn (t &Table) type_kind(typ Type) Kind {
if typ.nr_muls() > 0 || typ.has_flag(.optional) { if typ.nr_muls() > 0 || typ.has_flag(.optional) {
return Kind.placeholder return Kind.placeholder
} }
return table.get_type_symbol(typ).kind return t.get_type_symbol(typ).kind
} }
pub enum Kind { pub enum Kind {
@ -585,7 +585,7 @@ pub fn (mut t Table) register_builtin_type_symbols() {
cname: '__v_thread' cname: '__v_thread'
mod: 'builtin' mod: 'builtin'
info: Thread{ info: Thread{
return_type: table.void_type return_type: ast.void_type
} }
) )
t.register_type_symbol(kind: .interface_, name: 'IError', cname: 'IError', mod: 'builtin') t.register_type_symbol(kind: .interface_, name: 'IError', cname: 'IError', mod: 'builtin')
@ -688,7 +688,7 @@ pub:
attrs []Attr attrs []Attr
pub mut: pub mut:
embeds []Type embeds []Type
fields []Field fields []StructField
is_typedef bool // C. [typedef] is_typedef bool // C. [typedef]
is_union bool is_union bool
is_heap bool is_heap bool
@ -705,7 +705,7 @@ pub mut:
pub struct Interface { pub struct Interface {
pub mut: pub mut:
types []Type types []Type
fields []Field fields []StructField
methods []Fn methods []Fn
} }
@ -725,22 +725,23 @@ pub:
pub struct Aggregate { pub struct Aggregate {
mut: mut:
fields []Field // used for faster lookup inside the module fields []StructField // used for faster lookup inside the module
pub: pub:
types []Type types []Type
} }
// NB: FExpr here is a actually an ast.Expr . // NB: FExpr here is a actually an ast.Expr .
// It should always be used by casting to ast.Expr, using ast.fe2ex()/ast.ex2fe() // It should always be used by casting to ast.Expr, using ast.fe2ex()/ast.ex2fe()
// That hack is needed to break an import cycle between v.ast and v.table . // That hack is needed to break an import cycle between v.ast and v.ast .
pub type FExpr = byteptr | voidptr // pub type FExpr = byteptr | voidptr
/*
pub struct Field { pub struct Field {
pub: pub:
name string name string
pub mut: pub mut:
typ Type typ Type
default_expr FExpr default_expr Expr
has_default_expr bool has_default_expr bool
default_expr_typ Type default_expr_typ Type
default_val string default_val string
@ -749,8 +750,9 @@ pub mut:
is_mut bool is_mut bool
is_global bool is_global bool
} }
*/
pub fn (f &Field) equals(o &Field) bool { pub fn (f &StructField) equals(o &StructField) bool {
// TODO: f.is_mut == o.is_mut was removed here to allow read only access // TODO: f.is_mut == o.is_mut was removed here to allow read only access
// to (mut/not mut), but otherwise equal fields; some other new checks are needed: // to (mut/not mut), but otherwise equal fields; some other new checks are needed:
// - if node is declared mut, and we mutate node.stmts, all stmts fields must be mutable // - if node is declared mut, and we mutate node.stmts, all stmts fields must be mutable
@ -793,19 +795,19 @@ pub struct SumType {
pub: pub:
variants []Type variants []Type
pub mut: pub mut:
fields []Field fields []StructField
found_fields bool found_fields bool
} }
// human readable type name // human readable type name
pub fn (table &Table) type_to_str(t Type) string { pub fn (t &Table) type_to_str(typ Type) string {
return table.type_to_str_using_aliases(t, map[string]string{}) return t.type_to_str_using_aliases(typ, map[string]string{})
} }
// type name in code (for builtin) // type name in code (for builtin)
pub fn (mytable &Table) type_to_code(t Type) string { pub fn (mytable &Table) type_to_code(t Type) string {
match t { match t {
table.int_literal_type, table.float_literal_type { return mytable.get_type_symbol(t).kind.str() } ast.int_literal_type, ast.float_literal_type { return mytable.get_type_symbol(t).kind.str() }
else { return mytable.type_to_str_using_aliases(t, map[string]string{}) } else { return mytable.type_to_str_using_aliases(t, map[string]string{}) }
} }
} }
@ -824,7 +826,7 @@ pub fn (mytable &Table) type_to_str_using_aliases(t Type, import_aliases map[str
res = sym.kind.str() res = sym.kind.str()
} }
.array { .array {
if t == table.array_type { if t == ast.array_type {
return 'array' return 'array'
} }
if t.has_flag(.variadic) { if t.has_flag(.variadic) {
@ -869,7 +871,7 @@ pub fn (mytable &Table) type_to_str_using_aliases(t Type, import_aliases map[str
} }
} }
.map { .map {
if int(t) == table.map_type_idx { if int(t) == ast.map_type_idx {
return 'map' return 'map'
} }
info := sym.info as Map info := sym.info as Map
@ -969,7 +971,7 @@ pub fn (t &Table) fn_signature(func &Fn, opts FnSignatureOpts) string {
sb.write_string('$styp') sb.write_string('$styp')
} }
sb.write_string(')') sb.write_string(')')
if func.return_type != table.void_type { if func.return_type != ast.void_type {
sb.write_string(' ${t.type_to_str(func.return_type)}') sb.write_string(' ${t.type_to_str(func.return_type)}')
} }
return sb.str() return sb.str()
@ -1014,7 +1016,7 @@ pub fn (t &TypeSymbol) str_method_info() (bool, bool, int) {
return has_str_method, expects_ptr, nr_args return has_str_method, expects_ptr, nr_args
} }
pub fn (t &TypeSymbol) find_field(name string) ?Field { pub fn (t &TypeSymbol) find_field(name string) ?StructField {
match t.info { match t.info {
Aggregate { return t.info.find_field(name) } Aggregate { return t.info.find_field(name) }
Struct { return t.info.find_field(name) } Struct { return t.info.find_field(name) }
@ -1024,7 +1026,7 @@ pub fn (t &TypeSymbol) find_field(name string) ?Field {
} }
} }
fn (a &Aggregate) find_field(name string) ?Field { fn (a &Aggregate) find_field(name string) ?StructField {
for field in a.fields { for field in a.fields {
if field.name == name { if field.name == name {
return field return field
@ -1033,7 +1035,7 @@ fn (a &Aggregate) find_field(name string) ?Field {
return none return none
} }
pub fn (i &Interface) find_field(name string) ?Field { pub fn (i &Interface) find_field(name string) ?StructField {
for field in i.fields { for field in i.fields {
if field.name == name { if field.name == name {
return field return field
@ -1058,7 +1060,7 @@ pub fn (i &Interface) has_method(name string) bool {
return false return false
} }
pub fn (s Struct) find_field(name string) ?Field { pub fn (s Struct) find_field(name string) ?StructField {
for field in s.fields { for field in s.fields {
if field.name == name { if field.name == name {
return field return field
@ -1067,14 +1069,14 @@ pub fn (s Struct) find_field(name string) ?Field {
return none return none
} }
pub fn (s Struct) get_field(name string) Field { pub fn (s Struct) get_field(name string) StructField {
if field := s.find_field(name) { if field := s.find_field(name) {
return field return field
} }
panic('unknown field `$name`') panic('unknown field `$name`')
} }
pub fn (s &SumType) find_field(name string) ?Field { pub fn (s &SumType) find_field(name string) ?StructField {
for field in s.fields { for field in s.fields {
if field.name == name { if field.name == name {
return field return field

View File

@ -0,0 +1,81 @@
import v.ast
fn test_idx() {
mut t := ast.new_type(ast.void_type_idx)
assert t.idx() == ast.void_type_idx
t = ast.new_type(ast.i8_type_idx)
assert t.idx() == ast.i8_type_idx
}
fn test_muls() {
mut t := ast.new_type(ast.void_type_idx)
idx := t.idx()
assert t.nr_muls() == 0
for i in 0 .. 32 {
t = t.set_nr_muls(i)
assert t.nr_muls() == i
}
t = t.set_nr_muls(0)
assert t.nr_muls() == 0
assert t.is_ptr() == false
t = t.to_ptr()
assert t.nr_muls() == 1
assert t.is_ptr() == true
t = t.to_ptr()
assert t.nr_muls() == 2
assert t.is_ptr() == true
t = t.deref()
assert t.nr_muls() == 1
assert t.is_ptr() == true
t = t.deref()
assert t.nr_muls() == 0
assert t.is_ptr() == false
assert t.idx() == idx
}
fn test_flags() {
mut t := ast.new_type(ast.void_type_idx)
idx := t.idx()
nr_muls := t.nr_muls()
t = t.set_flag(ast.TypeFlag.optional)
assert t.has_flag(ast.TypeFlag.optional) == true
assert t.has_flag(ast.TypeFlag.variadic) == false
assert t.has_flag(ast.TypeFlag.generic) == false
t = t.set_flag(ast.TypeFlag.variadic)
assert t.has_flag(ast.TypeFlag.optional) == true
assert t.has_flag(ast.TypeFlag.variadic) == true
assert t.has_flag(ast.TypeFlag.generic) == false
t = t.set_flag(ast.TypeFlag.generic)
assert t.has_flag(ast.TypeFlag.optional) == true
assert t.has_flag(ast.TypeFlag.variadic) == true
assert t.has_flag(ast.TypeFlag.generic) == true
assert t.idx() == idx
assert t.nr_muls() == nr_muls
t = t.clear_flag(ast.TypeFlag.optional)
assert t.has_flag(ast.TypeFlag.optional) == false
assert t.has_flag(ast.TypeFlag.variadic) == true
assert t.has_flag(ast.TypeFlag.generic) == true
t = t.clear_flag(ast.TypeFlag.variadic)
assert t.has_flag(ast.TypeFlag.optional) == false
assert t.has_flag(ast.TypeFlag.variadic) == false
assert t.has_flag(ast.TypeFlag.generic) == true
t = t.clear_flag(ast.TypeFlag.generic)
assert t.has_flag(ast.TypeFlag.optional) == false
assert t.has_flag(ast.TypeFlag.variadic) == false
assert t.has_flag(ast.TypeFlag.generic) == false
assert t.idx() == idx
assert t.nr_muls() == nr_muls
}
fn test_derive() {
mut t := ast.new_type(ast.i8_type_idx)
t = t.set_flag(ast.TypeFlag.generic)
t = t.set_flag(ast.TypeFlag.variadic)
t = t.set_nr_muls(10)
mut t2 := ast.new_type(ast.i16_type_idx)
t2 = t2.derive(t)
assert t2.has_flag(ast.TypeFlag.optional) == false
assert t2.has_flag(ast.TypeFlag.variadic) == true
assert t2.has_flag(ast.TypeFlag.generic) == true
assert t2.nr_muls() == 10
}

View File

@ -1,11 +1,10 @@
import v.ast import v.ast
import v.ast.walker import v.ast.walker
import v.parser import v.parser
import v.table
import v.pref import v.pref
fn parse_text(text string) ast.File { fn parse_text(text string) ast.File {
tbl := table.new_table() tbl := ast.new_table()
prefs := pref.new_preferences() prefs := pref.new_preferences()
scope := &ast.Scope{ scope := &ast.Scope{
parent: 0 parent: 0

View File

@ -1,11 +1,10 @@
module builder module builder
import os import os
import v.ast
import v.token import v.token
import v.table
import v.pref import v.pref
import v.util import v.util
import v.ast
import v.vmod import v.vmod
import v.checker import v.checker
import v.parser import v.parser
@ -26,14 +25,14 @@ pub mut:
module_search_paths []string module_search_paths []string
parsed_files []ast.File parsed_files []ast.File
cached_msvc MsvcResult cached_msvc MsvcResult
table &table.Table table &ast.Table
ccoptions CcompilerOptions ccoptions CcompilerOptions
} }
pub fn new_builder(pref &pref.Preferences) Builder { pub fn new_builder(pref &pref.Preferences) Builder {
rdir := os.real_path(pref.path) rdir := os.real_path(pref.path)
compiled_dir := if os.is_dir(rdir) { rdir } else { os.dir(rdir) } compiled_dir := if os.is_dir(rdir) { rdir } else { os.dir(rdir) }
mut table := table.new_table() mut table := ast.new_table()
table.is_fmt = false table.is_fmt = false
if pref.use_color == .always { if pref.use_color == .always {
util.emanager.set_support_color(true) util.emanager.set_support_color(true)
@ -100,7 +99,7 @@ pub fn (mut b Builder) parse_imports() {
continue continue
} }
import_path := b.find_module_path(mod, ast_file.path) or { import_path := b.find_module_path(mod, ast_file.path) or {
// v.parsers[i].error_with_token_index('cannot import module "$mod" (not found)', v.parsers[i].import_table.get_import_tok_idx(mod)) // v.parsers[i].error_with_token_index('cannot import module "$mod" (not found)', v.parsers[i].import_ast.get_import_tok_idx(mod))
// break // break
error_with_pos('cannot import module "$mod" (not found)', ast_file.path, error_with_pos('cannot import module "$mod" (not found)', ast_file.path,
imp.pos) imp.pos)
@ -108,7 +107,7 @@ pub fn (mut b Builder) parse_imports() {
} }
v_files := b.v_files_from_dir(import_path) v_files := b.v_files_from_dir(import_path)
if v_files.len == 0 { if v_files.len == 0 {
// v.parsers[i].error_with_token_index('cannot import module "$mod" (no .v files in "$import_path")', v.parsers[i].import_table.get_import_tok_idx(mod)) // v.parsers[i].error_with_token_index('cannot import module "$mod" (no .v files in "$import_path")', v.parsers[i].import_ast.get_import_tok_idx(mod))
error_with_pos('cannot import module "$mod" (no .v files in "$import_path")', error_with_pos('cannot import module "$mod" (no .v files in "$import_path")',
ast_file.path, imp.pos) ast_file.path, imp.pos)
} }

View File

@ -430,8 +430,8 @@ fn (mut v Builder) setup_output_name() {
v.pref.cache_manager.save('.description.txt', v.pref.path, '${v.pref.path:-30} @ $v.pref.cache_manager.vopts\n') or { v.pref.cache_manager.save('.description.txt', v.pref.path, '${v.pref.path:-30} @ $v.pref.cache_manager.vopts\n') or {
panic(err) panic(err)
} }
// println('v.table.imports:') // println('v.ast.imports:')
// println(v.table.imports) // println(v.ast.imports)
} }
if os.is_dir(v.pref.out_name) { if os.is_dir(v.pref.out_name) {
verror("'$v.pref.out_name' is a directory") verror("'$v.pref.out_name' is a directory")
@ -913,15 +913,15 @@ fn (mut c Builder) cc_windows_cross() {
println(c.pref.out_name + ' has been successfully compiled') println(c.pref.out_name + ' has been successfully compiled')
} }
fn (mut v Builder) build_thirdparty_obj_files() { fn (mut b Builder) build_thirdparty_obj_files() {
v.log('build_thirdparty_obj_files: v.table.cflags: $v.table.cflags') b.log('build_thirdparty_obj_files: v.ast.cflags: $b.table.cflags')
for flag in v.get_os_cflags() { for flag in b.get_os_cflags() {
if flag.value.ends_with('.o') { if flag.value.ends_with('.o') {
rest_of_module_flags := v.get_rest_of_module_cflags(flag) rest_of_module_flags := b.get_rest_of_module_cflags(flag)
if v.pref.ccompiler == 'msvc' { if b.pref.ccompiler == 'msvc' {
v.build_thirdparty_obj_file_with_msvc(flag.value, rest_of_module_flags) b.build_thirdparty_obj_file_with_msvc(flag.value, rest_of_module_flags)
} else { } else {
v.build_thirdparty_obj_file(flag.value, rest_of_module_flags) b.build_thirdparty_obj_file(flag.value, rest_of_module_flags)
} }
} }
} }

View File

@ -260,7 +260,7 @@ pub fn (mut v Builder) cc_msvc() {
println('`builtin.obj` not found') println('`builtin.obj` not found')
exit(1) exit(1)
} }
for imp in v.table.imports { for imp in v.ast.imports {
if imp == 'webview' { if imp == 'webview' {
continue continue
} }

View File

@ -3,16 +3,15 @@
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module checker module checker
import v.table
import v.token
import v.ast import v.ast
import v.token
pub fn (mut c Checker) check_expected_call_arg(got table.Type, expected_ table.Type, language table.Language) ? { pub fn (mut c Checker) check_expected_call_arg(got ast.Type, expected_ ast.Type, language ast.Language) ? {
mut expected := expected_ mut expected := expected_
// variadic // variadic
if expected.has_flag(.variadic) { if expected.has_flag(.variadic) {
exp_type_sym := c.table.get_type_symbol(expected_) exp_type_sym := c.table.get_type_symbol(expected_)
exp_info := exp_type_sym.info as table.Array exp_info := exp_type_sym.info as ast.Array
expected = exp_info.elem_type expected = exp_info.elem_type
} }
if language == .c { if language == .c {
@ -21,29 +20,29 @@ pub fn (mut c Checker) check_expected_call_arg(got table.Type, expected_ table.T
return return
} }
// mode_t - currently using u32 as mode_t for C fns // mode_t - currently using u32 as mode_t for C fns
// if got.idx() in [table.int_type_idx, table.u32_type_idx] && expected.idx() in [table.int_type_idx, table.u32_type_idx] { // if got.idx() in [ast.int_type_idx, ast.u32_type_idx] && expected.idx() in [ast.int_type_idx, ast.u32_type_idx] {
// return // return
// } // }
// allow number to be used as size_t // allow number to be used as size_t
if got.is_number() && expected.idx() == table.size_t_type_idx { if got.is_number() && expected.idx() == ast.size_t_type_idx {
return return
} }
// allow bool & int to be used interchangeably for C functions // allow bool & int to be used interchangeably for C functions
if (got.idx() == table.bool_type_idx if (got.idx() == ast.bool_type_idx
&& expected.idx() in [table.int_type_idx, table.int_literal_type_idx]) && expected.idx() in [ast.int_type_idx, ast.int_literal_type_idx])
|| (expected.idx() == table.bool_type_idx || (expected.idx() == ast.bool_type_idx
&& got.idx() in [table.int_type_idx, table.int_literal_type_idx]) { && got.idx() in [ast.int_type_idx, ast.int_literal_type_idx]) {
return return
} }
if got.idx() == table.string_type_idx if got.idx() == ast.string_type_idx
&& expected in [table.byteptr_type_idx, table.charptr_type_idx] { && expected in [ast.byteptr_type_idx, ast.charptr_type_idx] {
return return
} }
exp_sym := c.table.get_type_symbol(expected) exp_sym := c.table.get_type_symbol(expected)
// unknown C types are set to int, allow int to be used for types like `&C.FILE` // unknown C types are set to int, allow int to be used for types like `&C.FILE`
// eg. `C.fflush(C.stderr)` - error: cannot use `int` as `&C.FILE` in argument 1 to `C.fflush` // eg. `C.fflush(C.stderr)` - error: cannot use `int` as `&C.FILE` in argument 1 to `C.fflush`
if expected.is_ptr() && exp_sym.language == .c && exp_sym.kind == .placeholder if expected.is_ptr() && exp_sym.language == .c && exp_sym.kind == .placeholder
&& got == table.int_type_idx { && got == ast.int_type_idx {
return return
} }
// return // return
@ -54,7 +53,7 @@ pub fn (mut c Checker) check_expected_call_arg(got table.Type, expected_ table.T
return error('cannot use `${c.table.type_to_str(got.clear_flag(.variadic))}` as `${c.table.type_to_str(expected.clear_flag(.variadic))}`') return error('cannot use `${c.table.type_to_str(got.clear_flag(.variadic))}` as `${c.table.type_to_str(expected.clear_flag(.variadic))}`')
} }
pub fn (mut c Checker) check_basic(got table.Type, expected table.Type) bool { pub fn (mut c Checker) check_basic(got ast.Type, expected ast.Type) bool {
got_, exp_ := c.table.unalias_num_type(got), c.table.unalias_num_type(expected) got_, exp_ := c.table.unalias_num_type(got), c.table.unalias_num_type(expected)
if got_.idx() == exp_.idx() { if got_.idx() == exp_.idx() {
// this is returning true even if one type is a ptr // this is returning true even if one type is a ptr
@ -65,11 +64,11 @@ pub fn (mut c Checker) check_basic(got table.Type, expected table.Type) bool {
return true return true
} }
// allow pointers to be initialized with 0. TODO: use none instead // allow pointers to be initialized with 0. TODO: use none instead
if expected.is_ptr() && got_ == table.int_literal_type { if expected.is_ptr() && got_ == ast.int_literal_type {
return true return true
} }
// TODO: use sym so it can be absorbed into below [.voidptr, .any] logic // TODO: use sym so it can be absorbed into below [.voidptr, .any] logic
if expected.idx() == table.array_type_idx || got.idx() == table.array_type_idx { if expected.idx() == ast.array_type_idx || got.idx() == ast.array_type_idx {
return true return true
} }
got_sym, exp_sym := c.table.get_type_symbol(got), c.table.get_type_symbol(expected) got_sym, exp_sym := c.table.get_type_symbol(got), c.table.get_type_symbol(expected)
@ -100,15 +99,15 @@ pub fn (mut c Checker) check_basic(got table.Type, expected table.Type) bool {
return c.check_matching_function_symbols(got_sym, exp_sym) return c.check_matching_function_symbols(got_sym, exp_sym)
} }
// allow using Error as a string for now (avoid a breaking change) // allow using Error as a string for now (avoid a breaking change)
if got == table.error_type_idx && expected == table.string_type_idx { if got == ast.error_type_idx && expected == ast.string_type_idx {
return true return true
} }
return false return false
} }
pub fn (mut c Checker) check_matching_function_symbols(got_type_sym &table.TypeSymbol, exp_type_sym &table.TypeSymbol) bool { pub fn (mut c Checker) check_matching_function_symbols(got_type_sym &ast.TypeSymbol, exp_type_sym &ast.TypeSymbol) bool {
got_info := got_type_sym.info as table.FnType got_info := got_type_sym.info as ast.FnType
exp_info := exp_type_sym.info as table.FnType exp_info := exp_type_sym.info as ast.FnType
got_fn := got_info.func got_fn := got_info.func
exp_fn := exp_info.func exp_fn := exp_info.func
// we are using check() to compare return type & args as they might include // we are using check() to compare return type & args as they might include
@ -137,39 +136,39 @@ pub fn (mut c Checker) check_matching_function_symbols(got_type_sym &table.TypeS
} }
[inline] [inline]
fn (mut c Checker) check_shift(left_type table.Type, right_type table.Type, left_pos token.Position, right_pos token.Position) table.Type { fn (mut c Checker) check_shift(left_type ast.Type, right_type ast.Type, left_pos token.Position, right_pos token.Position) ast.Type {
if !left_type.is_int() { if !left_type.is_int() {
// maybe it's an int alias? TODO move this to is_int() ? // maybe it's an int alias? TODO move this to is_int() ?
sym := c.table.get_type_symbol(left_type) sym := c.table.get_type_symbol(left_type)
if sym.kind == .alias && (sym.info as table.Alias).parent_type.is_int() { if sym.kind == .alias && (sym.info as ast.Alias).parent_type.is_int() {
return left_type return left_type
} }
if c.pref.translated && left_type == table.bool_type { if c.pref.translated && left_type == ast.bool_type {
// allow `bool << 2` in translated C code // allow `bool << 2` in translated C code
return table.int_type return ast.int_type
} }
c.error('invalid operation: shift on type `$sym.name`', left_pos) c.error('invalid operation: shift on type `$sym.name`', left_pos)
return table.void_type return ast.void_type
} else if !right_type.is_int() { } else if !right_type.is_int() {
c.error('cannot shift non-integer type `${c.table.get_type_symbol(right_type).name}` into type `${c.table.get_type_symbol(left_type).name}`', c.error('cannot shift non-integer type `${c.table.get_type_symbol(right_type).name}` into type `${c.table.get_type_symbol(left_type).name}`',
right_pos) right_pos)
return table.void_type return ast.void_type
} }
return left_type return left_type
} }
pub fn (c &Checker) promote(left_type table.Type, right_type table.Type) table.Type { pub fn (c &Checker) promote(left_type ast.Type, right_type ast.Type) ast.Type {
if left_type.is_ptr() || left_type.is_pointer() { if left_type.is_ptr() || left_type.is_pointer() {
if right_type.is_int() { if right_type.is_int() {
return left_type return left_type
} else { } else {
return table.void_type return ast.void_type
} }
} else if right_type.is_ptr() || right_type.is_pointer() { } else if right_type.is_ptr() || right_type.is_pointer() {
if left_type.is_int() { if left_type.is_int() {
return right_type return right_type
} else { } else {
return table.void_type return ast.void_type
} }
} }
if left_type == right_type { if left_type == right_type {
@ -179,13 +178,13 @@ pub fn (c &Checker) promote(left_type table.Type, right_type table.Type) table.T
return c.promote_num(left_type, right_type) return c.promote_num(left_type, right_type)
} else if left_type.has_flag(.optional) != right_type.has_flag(.optional) { } else if left_type.has_flag(.optional) != right_type.has_flag(.optional) {
// incompatible // incompatible
return table.void_type return ast.void_type
} else { } else {
return left_type // default to left if not automatic promotion possible return left_type // default to left if not automatic promotion possible
} }
} }
fn (c &Checker) promote_num(left_type table.Type, right_type table.Type) table.Type { fn (c &Checker) promote_num(left_type ast.Type, right_type ast.Type) ast.Type {
// sort the operands to save time // sort the operands to save time
mut type_hi := left_type mut type_hi := left_type
mut type_lo := right_type mut type_lo := right_type
@ -195,38 +194,38 @@ fn (c &Checker) promote_num(left_type table.Type, right_type table.Type) table.T
idx_hi := type_hi.idx() idx_hi := type_hi.idx()
idx_lo := type_lo.idx() idx_lo := type_lo.idx()
// the following comparisons rely on the order of the indices in table/types.v // the following comparisons rely on the order of the indices in table/types.v
if idx_hi == table.int_literal_type_idx { if idx_hi == ast.int_literal_type_idx {
return type_lo return type_lo
} else if idx_hi == table.float_literal_type_idx { } else if idx_hi == ast.float_literal_type_idx {
if idx_lo in table.float_type_idxs { if idx_lo in ast.float_type_idxs {
return type_lo return type_lo
} else { } else {
return table.void_type return ast.void_type
} }
} else if type_hi.is_float() { } else if type_hi.is_float() {
if idx_hi == table.f32_type_idx { if idx_hi == ast.f32_type_idx {
if idx_lo in [table.i64_type_idx, table.u64_type_idx] { if idx_lo in [ast.i64_type_idx, ast.u64_type_idx] {
return table.void_type return ast.void_type
} else { } else {
return type_hi return type_hi
} }
} else { // f64, float_literal } else { // f64, float_literal
return type_hi return type_hi
} }
} else if idx_lo >= table.byte_type_idx { // both operands are unsigned } else if idx_lo >= ast.byte_type_idx { // both operands are unsigned
return type_hi return type_hi
} else if idx_lo >= table.i8_type_idx } else if idx_lo >= ast.i8_type_idx
&& (idx_hi <= table.i64_type_idx || idx_hi == table.rune_type_idx) { // both signed && (idx_hi <= ast.i64_type_idx || idx_hi == ast.rune_type_idx) { // both signed
return if idx_lo == table.i64_type_idx { type_lo } else { type_hi } return if idx_lo == ast.i64_type_idx { type_lo } else { type_hi }
} else if idx_hi - idx_lo < (table.byte_type_idx - table.i8_type_idx) { } else if idx_hi - idx_lo < (ast.byte_type_idx - ast.i8_type_idx) {
return type_lo // conversion unsigned -> signed if signed type is larger return type_lo // conversion unsigned -> signed if signed type is larger
} else { } else {
return table.void_type // conversion signed -> unsigned not allowed return ast.void_type // conversion signed -> unsigned not allowed
} }
} }
// TODO: promote(), check_types(), symmetric_check() and check() overlap - should be rearranged // TODO: promote(), check_types(), symmetric_check() and check() overlap - should be rearranged
pub fn (mut c Checker) check_types(got table.Type, expected table.Type) bool { pub fn (mut c Checker) check_types(got ast.Type, expected ast.Type) bool {
if got == expected { if got == expected {
return true return true
} }
@ -242,7 +241,7 @@ pub fn (mut c Checker) check_types(got table.Type, expected table.Type) bool {
if exp_idx == got_idx { if exp_idx == got_idx {
return true return true
} }
if exp_idx == table.voidptr_type_idx || exp_idx == table.byteptr_type_idx { if exp_idx == ast.voidptr_type_idx || exp_idx == ast.byteptr_type_idx {
if got.is_ptr() || got.is_pointer() { if got.is_ptr() || got.is_pointer() {
return true return true
} }
@ -250,25 +249,25 @@ pub fn (mut c Checker) check_types(got table.Type, expected table.Type) bool {
// allow direct int-literal assignment for pointers for now // allow direct int-literal assignment for pointers for now
// maybe in the future optionals should be used for that // maybe in the future optionals should be used for that
if expected.is_ptr() || expected.is_pointer() { if expected.is_ptr() || expected.is_pointer() {
if got == table.int_literal_type { if got == ast.int_literal_type {
return true return true
} }
} }
if got_idx == table.voidptr_type_idx || got_idx == table.byteptr_type_idx { if got_idx == ast.voidptr_type_idx || got_idx == ast.byteptr_type_idx {
if expected.is_ptr() || expected.is_pointer() { if expected.is_ptr() || expected.is_pointer() {
return true return true
} }
} }
if expected == table.charptr_type && got == table.char_type.to_ptr() { if expected == ast.charptr_type && got == ast.char_type.to_ptr() {
return true return true
} }
if !c.check_basic(got, expected) { // TODO: this should go away... if !c.check_basic(got, expected) { // TODO: this should go away...
return false return false
} }
if got.is_number() && expected.is_number() { if got.is_number() && expected.is_number() {
if got == table.rune_type && expected == table.byte_type { if got == ast.rune_type && expected == ast.byte_type {
return true return true
} else if expected == table.rune_type && got == table.byte_type { } else if expected == ast.rune_type && got == ast.byte_type {
return true return true
} }
if c.promote_num(expected, got) != expected { if c.promote_num(expected, got) != expected {
@ -282,7 +281,7 @@ pub fn (mut c Checker) check_types(got table.Type, expected table.Type) bool {
return true return true
} }
pub fn (mut c Checker) check_expected(got table.Type, expected table.Type) ? { pub fn (mut c Checker) check_expected(got ast.Type, expected ast.Type) ? {
if c.check_types(got, expected) { if c.check_types(got, expected) {
return return
} }
@ -290,30 +289,30 @@ pub fn (mut c Checker) check_expected(got table.Type, expected table.Type) ? {
} }
[inline] [inline]
fn (c &Checker) expected_msg(got table.Type, expected table.Type) string { fn (c &Checker) expected_msg(got ast.Type, expected ast.Type) string {
exps := c.table.type_to_str(expected) exps := c.table.type_to_str(expected)
gots := c.table.type_to_str(got) gots := c.table.type_to_str(got)
return 'expected `$exps`, not `$gots`' return 'expected `$exps`, not `$gots`'
} }
pub fn (mut c Checker) symmetric_check(left table.Type, right table.Type) bool { pub fn (mut c Checker) symmetric_check(left ast.Type, right ast.Type) bool {
// allow direct int-literal assignment for pointers for now // allow direct int-literal assignment for pointers for now
// maybe in the future optionals should be used for that // maybe in the future optionals should be used for that
if right.is_ptr() || right.is_pointer() { if right.is_ptr() || right.is_pointer() {
if left == table.int_literal_type { if left == ast.int_literal_type {
return true return true
} }
} }
// allow direct int-literal assignment for pointers for now // allow direct int-literal assignment for pointers for now
if left.is_ptr() || left.is_pointer() { if left.is_ptr() || left.is_pointer() {
if right == table.int_literal_type { if right == ast.int_literal_type {
return true return true
} }
} }
return c.check_basic(left, right) return c.check_basic(left, right)
} }
pub fn (c &Checker) get_default_fmt(ftyp table.Type, typ table.Type) byte { pub fn (c &Checker) get_default_fmt(ftyp ast.Type, typ ast.Type) byte {
if ftyp.has_flag(.optional) { if ftyp.has_flag(.optional) {
return `s` return `s`
} else if typ.is_float() { } else if typ.is_float() {
@ -328,16 +327,16 @@ pub fn (c &Checker) get_default_fmt(ftyp table.Type, typ table.Type) byte {
mut sym := c.table.get_type_symbol(c.unwrap_generic(ftyp)) mut sym := c.table.get_type_symbol(c.unwrap_generic(ftyp))
if sym.kind == .alias { if sym.kind == .alias {
// string aliases should be printable // string aliases should be printable
info := sym.info as table.Alias info := sym.info as ast.Alias
sym = c.table.get_type_symbol(info.parent_type) sym = c.table.get_type_symbol(info.parent_type)
if info.parent_type == table.string_type { if info.parent_type == ast.string_type {
return `s` return `s`
} }
} }
if sym.kind == .function { if sym.kind == .function {
return `s` return `s`
} }
if ftyp in [table.string_type, table.bool_type] if ftyp in [ast.string_type, ast.bool_type]
|| sym.kind in [.enum_, .array, .array_fixed, .struct_, .map, .multi_return, .sum_type, .interface_, .none_] || sym.kind in [.enum_, .array, .array_fixed, .struct_, .map, .multi_return, .sum_type, .interface_, .none_]
|| ftyp.has_flag(.optional) || sym.has_method('str') { || ftyp.has_flag(.optional) || sym.has_method('str') {
return `s` return `s`
@ -347,7 +346,7 @@ pub fn (c &Checker) get_default_fmt(ftyp table.Type, typ table.Type) byte {
} }
} }
pub fn (mut c Checker) fail_if_unreadable(expr ast.Expr, typ table.Type, what string) { pub fn (mut c Checker) fail_if_unreadable(expr ast.Expr, typ ast.Type, what string) {
mut pos := token.Position{} mut pos := token.Position{}
match expr { match expr {
ast.Ident { ast.Ident {
@ -376,7 +375,7 @@ pub fn (mut c Checker) fail_if_unreadable(expr ast.Expr, typ table.Type, what st
} }
} }
pub fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) table.Type { pub fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) ast.Type {
inside_println_arg_save := c.inside_println_arg inside_println_arg_save := c.inside_println_arg
c.inside_println_arg = true c.inside_println_arg = true
for i, expr in node.exprs { for i, expr in node.exprs {
@ -392,7 +391,7 @@ pub fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) table.T
if fmt == `_` { // set default representation for type if none has been given if fmt == `_` { // set default representation for type if none has been given
fmt = c.get_default_fmt(ftyp, typ) fmt = c.get_default_fmt(ftyp, typ)
if fmt == `_` { if fmt == `_` {
if typ != table.void_type { if typ != ast.void_type {
c.error('no known default format for type `${c.table.get_type_name(ftyp)}`', c.error('no known default format for type `${c.table.get_type_name(ftyp)}`',
node.fmt_poss[i]) node.fmt_poss[i])
} }
@ -413,7 +412,7 @@ pub fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) table.T
|| (typ.is_float() && fmt !in [`E`, `F`, `G`, `e`, `f`, `g`]) || (typ.is_float() && fmt !in [`E`, `F`, `G`, `e`, `f`, `g`])
|| (typ.is_pointer() && fmt !in [`p`, `x`, `X`]) || (typ.is_pointer() && fmt !in [`p`, `x`, `X`])
|| (typ.is_string() && fmt != `s`) || (typ.is_string() && fmt != `s`)
|| (typ.idx() in [table.i64_type_idx, table.f64_type_idx] && fmt == `c`) { || (typ.idx() in [ast.i64_type_idx, ast.f64_type_idx] && fmt == `c`) {
c.error('illegal format specifier `${fmt:c}` for type `${c.table.get_type_name(ftyp)}`', c.error('illegal format specifier `${fmt:c}` for type `${c.table.get_type_name(ftyp)}`',
node.fmt_poss[i]) node.fmt_poss[i])
} }
@ -425,18 +424,18 @@ pub fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) table.T
} }
} }
c.inside_println_arg = inside_println_arg_save c.inside_println_arg = inside_println_arg_save
return table.string_type return ast.string_type
} }
pub fn (mut c Checker) infer_fn_types(f table.Fn, mut call_expr ast.CallExpr) { pub fn (mut c Checker) infer_fn_types(f ast.Fn, mut call_expr ast.CallExpr) {
mut inferred_types := []table.Type{} mut inferred_types := []ast.Type{}
for gi, gt_name in f.generic_names { for gi, gt_name in f.generic_names {
// skip known types // skip known types
if gi < call_expr.generic_types.len { if gi < call_expr.generic_types.len {
inferred_types << call_expr.generic_types[gi] inferred_types << call_expr.generic_types[gi]
continue continue
} }
mut typ := table.void_type mut typ := ast.void_type
for i, param in f.params { for i, param in f.params {
arg_i := if i != 0 && call_expr.is_method { i - 1 } else { i } arg_i := if i != 0 && call_expr.is_method { i - 1 } else { i }
if call_expr.args.len <= arg_i { if call_expr.args.len <= arg_i {
@ -453,16 +452,16 @@ pub fn (mut c Checker) infer_fn_types(f table.Fn, mut call_expr ast.CallExpr) {
} }
arg_sym := c.table.get_type_symbol(arg.typ) arg_sym := c.table.get_type_symbol(arg.typ)
if arg_sym.kind == .array && param_type_sym.kind == .array { if arg_sym.kind == .array && param_type_sym.kind == .array {
mut arg_elem_info := arg_sym.info as table.Array mut arg_elem_info := arg_sym.info as ast.Array
mut param_elem_info := param_type_sym.info as table.Array mut param_elem_info := param_type_sym.info as ast.Array
mut arg_elem_sym := c.table.get_type_symbol(arg_elem_info.elem_type) mut arg_elem_sym := c.table.get_type_symbol(arg_elem_info.elem_type)
mut param_elem_sym := c.table.get_type_symbol(param_elem_info.elem_type) mut param_elem_sym := c.table.get_type_symbol(param_elem_info.elem_type)
for { for {
if arg_elem_sym.kind == .array && param_elem_sym.kind == .array if arg_elem_sym.kind == .array && param_elem_sym.kind == .array
&& c.cur_fn.generic_params.filter(it.name == param_elem_sym.name).len == 0 { && c.cur_fn.generic_params.filter(it.name == param_elem_sym.name).len == 0 {
arg_elem_info = arg_elem_sym.info as table.Array arg_elem_info = arg_elem_sym.info as ast.Array
arg_elem_sym = c.table.get_type_symbol(arg_elem_info.elem_type) arg_elem_sym = c.table.get_type_symbol(arg_elem_info.elem_type)
param_elem_info = param_elem_sym.info as table.Array param_elem_info = param_elem_sym.info as ast.Array
param_elem_sym = c.table.get_type_symbol(param_elem_info.elem_type) param_elem_sym = c.table.get_type_symbol(param_elem_info.elem_type)
} else { } else {
typ = arg_elem_info.elem_type typ = arg_elem_info.elem_type
@ -475,7 +474,7 @@ pub fn (mut c Checker) infer_fn_types(f table.Fn, mut call_expr ast.CallExpr) {
break break
} }
} }
if typ == table.void_type { if typ == ast.void_type {
c.error('could not infer generic type `$gt_name` in call to `$f.name`', call_expr.pos) c.error('could not infer generic type `$gt_name` in call to `$f.name`', call_expr.pos)
return return
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,7 @@
vlib/v/checker/tests/comparing_typesymbol_to_a_type_should_not_compile.vv:12:7: error: possible type mismatch of compared values of `==` operation vlib/v/checker/tests/comparing_typesymbol_to_a_type_should_not_compile.vv:12:7: error: possible type mismatch of compared values of `==` operation
10 | x := ityp == table.string_type 10 | x := ityp == ast.string_type
11 | // the next line should produce at least a warning, or even an error, without an explicit cast: 11 | // the next line should produce at least a warning, or even an error, without an explicit cast:
12 | z := isym == table.string_type 12 | z := isym == ast.string_type
| ~~~~~~~~~~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~~~~~~~~
13 | println(typeof(isym).name) 13 | println(typeof(isym).name)
14 | println(typeof(table.string_type).name) 14 | println(typeof(ast.string_type).name)

View File

@ -1,17 +1,17 @@
import v.table import v.ast
fn main() { fn main() {
t := table.new_table() t := ast.new_table()
ityp := table.int_type ityp := ast.int_type
isym := t.get_type_symbol(ityp) isym := t.get_type_symbol(ityp)
println(ityp.debug()) println(ityp.debug())
println(isym) println(isym)
println(isym.debug()) println(isym.debug())
x := ityp == table.string_type x := ityp == ast.string_type
// the next line should produce at least a warning, or even an error, without an explicit cast: // the next line should produce at least a warning, or even an error, without an explicit cast:
z := isym == table.string_type z := isym == ast.string_type
println(typeof(isym).name) println(typeof(isym).name)
println(typeof(table.string_type).name) println(typeof(ast.string_type).name)
println(x) println(x)
println(z) println(z)
} }

View File

@ -8,7 +8,6 @@ import v.fmt
import v.parser import v.parser
import v.pref import v.pref
import v.scanner import v.scanner
import v.table
import v.token import v.token
// SymbolKind categorizes the symbols it documents. // SymbolKind categorizes the symbols it documents.
@ -92,7 +91,7 @@ pub struct Doc {
pub mut: pub mut:
prefs &pref.Preferences = new_vdoc_preferences() prefs &pref.Preferences = new_vdoc_preferences()
base_path string base_path string
table &table.Table = &table.Table{} table &ast.Table = &ast.Table{}
checker checker.Checker = checker.Checker{ checker checker.Checker = checker.Checker{
table: 0 table: 0
cur_fn: 0 cur_fn: 0
@ -152,7 +151,7 @@ pub fn new_vdoc_preferences() &pref.Preferences {
pub fn new(input_path string) Doc { pub fn new(input_path string) Doc {
mut d := Doc{ mut d := Doc{
base_path: os.real_path(input_path) base_path: os.real_path(input_path)
table: table.new_table() table: ast.new_table()
head: DocNode{} head: DocNode{}
contents: map[string]DocNode{} contents: map[string]DocNode{}
time_generated: time.now() time_generated: time.now()

View File

@ -1,4 +1,4 @@
// import v.table // import v.ast
import v.doc import v.doc
// fn test_generate_with_pos() {} // fn test_generate_with_pos() {}

View File

@ -1,9 +1,8 @@
module doc module doc
import os import os
import v.table
import v.parser
import v.ast import v.ast
import v.parser
import v.pref import v.pref
// get_parent_mod returns the parent mod name, in dot format. // get_parent_mod returns the parent mod name, in dot format.
@ -40,7 +39,7 @@ fn get_parent_mod(input_dir string) ?string {
} }
return error('No V files found.') return error('No V files found.')
} }
tbl := table.new_table() tbl := ast.new_table()
scope := &ast.Scope{ scope := &ast.Scope{
parent: 0 parent: 0
} }

View File

@ -3,7 +3,6 @@ module doc
import strings import strings
import v.ast import v.ast
import v.token import v.token
import v.table
// merge_comments merges all the comment contents into a single text. // merge_comments merges all the comment contents into a single text.
pub fn merge_comments(comments []ast.Comment) string { pub fn merge_comments(comments []ast.Comment) string {
@ -140,9 +139,9 @@ pub fn (d Doc) stmt_pub(stmt ast.Stmt) bool {
} }
} }
// type_to_str is a wrapper function around `fmt.table.type_to_str`. // type_to_str is a wrapper function around `fmt.ast.type_to_str`.
pub fn (mut d Doc) type_to_str(typ table.Type) string { pub fn (mut d Doc) type_to_str(typ ast.Type) string {
// why is it the default behaviour of table.type_to_str // why is it the default behaviour of ast.type_to_str
// to convert math.bits.Type to bits.Type? // to convert math.bits.Type to bits.Type?
d.table.cmod_prefix = d.orig_mod_name + '.' d.table.cmod_prefix = d.orig_mod_name + '.'
return d.fmt.table.type_to_str(typ).all_after('&') return d.fmt.table.type_to_str(typ).all_after('&')

View File

@ -5,7 +5,6 @@ module eval
import v.ast import v.ast
import v.checker import v.checker
import v.table
import v.pref import v.pref
pub type Object = int | string pub type Object = int | string
@ -14,14 +13,14 @@ pub struct Eval {
mut: mut:
checker checker.Checker checker checker.Checker
vars map[string]Var vars map[string]Var
table &table.Table table &ast.Table
} }
pub struct Var { pub struct Var {
value Object value Object
} }
pub fn (mut e Eval) eval(file ast.File, table &table.Table) string { pub fn (mut e Eval) eval(file ast.File, table &ast.Table) string {
vpref := &pref.Preferences{} vpref := &pref.Preferences{}
e.table = table e.table = table
mut res := '' mut res := ''

View File

@ -3,9 +3,9 @@
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module fmt module fmt
import v.table import v.ast
pub fn (mut f Fmt) attrs(attrs []table.Attr) { pub fn (mut f Fmt) attrs(attrs []ast.Attr) {
mut sorted_attrs := attrs.clone() mut sorted_attrs := attrs.clone()
// Sort the attributes. The ones with arguments come first. // Sort the attributes. The ones with arguments come first.
sorted_attrs.sort(a.arg.len > b.arg.len) sorted_attrs.sort(a.arg.len > b.arg.len)
@ -22,7 +22,7 @@ pub struct AttrsOptions {
inline bool inline bool
} }
pub fn (mut f Fmt) single_line_attrs(attrs []table.Attr, options AttrsOptions) { pub fn (mut f Fmt) single_line_attrs(attrs []ast.Attr, options AttrsOptions) {
if attrs.len == 0 { if attrs.len == 0 {
return return
} }
@ -44,7 +44,7 @@ pub fn (mut f Fmt) single_line_attrs(attrs []table.Attr, options AttrsOptions) {
} }
} }
fn inline_attrs_len(attrs []table.Attr) int { fn inline_attrs_len(attrs []ast.Attr) int {
if attrs.len == 0 { if attrs.len == 0 {
return 0 return 0
} }

View File

@ -5,7 +5,6 @@ module fmt
import math.mathutil as mu import math.mathutil as mu
import v.ast import v.ast
import v.table
import strings import strings
import v.util import v.util
import v.pref import v.pref
@ -18,7 +17,7 @@ const (
pub struct Fmt { pub struct Fmt {
pub mut: pub mut:
table &table.Table table &ast.Table
out_imports strings.Builder out_imports strings.Builder
out strings.Builder out strings.Builder
indent int indent int
@ -49,7 +48,7 @@ pub mut:
pref &pref.Preferences pref &pref.Preferences
} }
pub fn fmt(file ast.File, table &table.Table, pref &pref.Preferences, is_debug bool) string { pub fn fmt(file ast.File, table &ast.Table, pref &pref.Preferences, is_debug bool) string {
mut f := Fmt{ mut f := Fmt{
out: strings.new_builder(1000) out: strings.new_builder(1000)
out_imports: strings.new_builder(200) out_imports: strings.new_builder(200)
@ -113,7 +112,7 @@ fn (mut f Fmt) write_indent() {
f.line_len += f.indent * 4 f.line_len += f.indent * 4
} }
fn (mut f Fmt) write_language_prefix(lang table.Language) { fn (mut f Fmt) write_language_prefix(lang ast.Language) {
match lang { match lang {
.c { f.write('C.') } .c { f.write('C.') }
.js { f.write('JS.') } .js { f.write('JS.') }
@ -223,7 +222,7 @@ pub fn (mut f Fmt) short_module(name string) string {
//=== Import-related methods ===// //=== Import-related methods ===//
pub fn (mut f Fmt) mark_types_import_as_used(typ table.Type) { pub fn (mut f Fmt) mark_types_import_as_used(typ ast.Type) {
sym := f.table.get_type_symbol(typ) sym := f.table.get_type_symbol(typ)
f.mark_import_as_used(sym.name) f.mark_import_as_used(sym.name)
} }
@ -617,7 +616,7 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
ast.StructInit { ast.StructInit {
f.struct_init(node) f.struct_init(node)
} }
ast.Type { ast.TypeNode {
f.type_expr(node) f.type_expr(node)
} }
ast.TypeOf { ast.TypeOf {
@ -1261,7 +1260,7 @@ pub fn (mut f Fmt) fn_type_decl(node ast.FnTypeDecl) {
f.write('pub ') f.write('pub ')
} }
typ_sym := f.table.get_type_symbol(node.typ) typ_sym := f.table.get_type_symbol(node.typ)
fn_typ_info := typ_sym.info as table.FnType fn_typ_info := typ_sym.info as ast.FnType
fn_info := fn_typ_info.func fn_info := fn_typ_info.func
fn_name := f.no_cur_mod(node.name) fn_name := f.no_cur_mod(node.name)
f.write('type $fn_name = fn (') f.write('type $fn_name = fn (')
@ -1293,7 +1292,7 @@ pub fn (mut f Fmt) fn_type_decl(node ast.FnTypeDecl) {
} }
} }
f.write(')') f.write(')')
if fn_info.return_type.idx() != table.void_type_idx { if fn_info.return_type.idx() != ast.void_type_idx {
ret_str := f.no_cur_mod(f.table.type_to_str_using_aliases(fn_info.return_type, ret_str := f.no_cur_mod(f.table.type_to_str_using_aliases(fn_info.return_type,
f.mod2alias)) f.mod2alias))
f.write(' $ret_str') f.write(' $ret_str')
@ -1335,7 +1334,7 @@ pub fn (mut f Fmt) array_decompose(node ast.ArrayDecompose) {
} }
pub fn (mut f Fmt) array_init(node ast.ArrayInit) { pub fn (mut f Fmt) array_init(node ast.ArrayInit) {
if node.exprs.len == 0 && node.typ != 0 && node.typ != table.void_type { if node.exprs.len == 0 && node.typ != 0 && node.typ != ast.void_type {
// `x := []string{}` // `x := []string{}`
f.mark_types_import_as_used(node.typ) f.mark_types_import_as_used(node.typ)
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias)) f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias))
@ -1530,7 +1529,7 @@ pub fn (mut f Fmt) call_expr(node ast.CallExpr) {
f.use_short_fn_args = false f.use_short_fn_args = false
if node.args.len > 0 && node.args.last().expr is ast.StructInit { if node.args.len > 0 && node.args.last().expr is ast.StructInit {
struct_expr := node.args.last().expr as ast.StructInit struct_expr := node.args.last().expr as ast.StructInit
if struct_expr.typ == table.void_type { if struct_expr.typ == ast.void_type {
f.use_short_fn_args = true f.use_short_fn_args = true
} }
} }
@ -2005,7 +2004,7 @@ pub fn (mut f Fmt) lock_expr(node ast.LockExpr) {
pub fn (mut f Fmt) map_init(node ast.MapInit) { pub fn (mut f Fmt) map_init(node ast.MapInit) {
if node.keys.len == 0 { if node.keys.len == 0 {
if node.typ > table.void_type { if node.typ > ast.void_type {
f.mark_types_import_as_used(node.typ) f.mark_types_import_as_used(node.typ)
f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias)) f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias))
} else { } else {
@ -2269,7 +2268,7 @@ pub fn (mut f Fmt) string_literal(node ast.StringLiteral) {
use_double_quote := node.val.contains("'") && !node.val.contains('"') use_double_quote := node.val.contains("'") && !node.val.contains('"')
if node.is_raw { if node.is_raw {
f.write('r') f.write('r')
} else if node.language == table.Language.c { } else if node.language == ast.Language.c {
f.write('c') f.write('c')
} }
if node.is_raw { if node.is_raw {
@ -2323,7 +2322,7 @@ pub fn (mut f Fmt) string_inter_literal(node ast.StringInterLiteral) {
f.write(quote) f.write(quote)
} }
pub fn (mut f Fmt) type_expr(node ast.Type) { pub fn (mut f Fmt) type_expr(node ast.TypeNode) {
f.write(f.table.type_to_str(node.typ)) f.write(f.table.type_to_str(node.typ))
} }

View File

@ -4,10 +4,9 @@
import os import os
import term import term
import benchmark import benchmark
import v.ast
import v.fmt import v.fmt
import v.parser import v.parser
import v.table import v.ast
import v.pref import v.pref
import v.util import v.util
import v.util.vtest import v.util.vtest
@ -54,7 +53,7 @@ fn test_fmt() {
eprintln(fmt_bench.step_message_fail('cannot read from $vrelpath')) eprintln(fmt_bench.step_message_fail('cannot read from $vrelpath'))
continue continue
} }
table := table.new_table() table := ast.new_table()
file_ast := parser.parse_file(ipath, table, .parse_comments, fpref, &ast.Scope{ file_ast := parser.parse_file(ipath, table, .parse_comments, fpref, &ast.Scope{
parent: 0 parent: 0
}) })

View File

@ -7,7 +7,6 @@ import benchmark
import v.ast import v.ast
import v.fmt import v.fmt
import v.parser import v.parser
import v.table
import v.pref import v.pref
import v.util import v.util
@ -49,7 +48,7 @@ fn test_fmt() {
eprintln(fmt_bench.step_message_fail('cannot read from $opath')) eprintln(fmt_bench.step_message_fail('cannot read from $opath'))
continue continue
} }
table := table.new_table() table := ast.new_table()
file_ast := parser.parse_file(ipath, table, .parse_comments, fpref, &ast.Scope{ file_ast := parser.parse_file(ipath, table, .parse_comments, fpref, &ast.Scope{
parent: 0 parent: 0
}) })

View File

@ -7,7 +7,6 @@ import benchmark
import v.ast import v.ast
import v.fmt import v.fmt
import v.parser import v.parser
import v.table
import v.pref import v.pref
import v.util import v.util
@ -47,7 +46,7 @@ fn test_vlib_fmt() {
eprintln(fmt_bench.step_message_fail('cannot read from $opath')) eprintln(fmt_bench.step_message_fail('cannot read from $opath'))
continue continue
} }
table := table.new_table() table := ast.new_table()
file_ast := parser.parse_file(ipath, table, .parse_comments, fpref, &ast.Scope{ file_ast := parser.parse_file(ipath, table, .parse_comments, fpref, &ast.Scope{
parent: 0 parent: 0
}) })

View File

@ -4,7 +4,6 @@ module c
import strings import strings
import v.ast import v.ast
import v.table
fn (mut g Gen) array_init(node ast.ArrayInit) { fn (mut g Gen) array_init(node ast.ArrayInit) {
type_sym := g.table.get_type_symbol(node.typ) type_sym := g.table.get_type_symbol(node.typ)
@ -36,7 +35,7 @@ fn (mut g Gen) array_init(node ast.ArrayInit) {
} }
} else if node.has_default { } else if node.has_default {
g.expr(node.default_expr) g.expr(node.default_expr)
info := type_sym.info as table.ArrayFixed info := type_sym.info as ast.ArrayFixed
for _ in 1 .. info.size { for _ in 1 .. info.size {
g.write(', ') g.write(', ')
g.expr(node.default_expr) g.expr(node.default_expr)
@ -81,7 +80,7 @@ fn (mut g Gen) array_init(node ast.ArrayInit) {
g.write('&($elem_type_str[]){') g.write('&($elem_type_str[]){')
g.expr(node.default_expr) g.expr(node.default_expr)
g.write('})') g.write('})')
} else if node.has_len && node.elem_type == table.string_type { } else if node.has_len && node.elem_type == ast.string_type {
g.write('&($elem_type_str[]){') g.write('&($elem_type_str[]){')
g.write('_SLIT("")') g.write('_SLIT("")')
g.write('})') g.write('})')
@ -134,9 +133,9 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) {
// inp_typ := g.typ(node.receiver_type) // inp_typ := g.typ(node.receiver_type)
ret_sym := g.table.get_type_symbol(node.return_type) ret_sym := g.table.get_type_symbol(node.return_type)
inp_sym := g.table.get_type_symbol(node.receiver_type) inp_sym := g.table.get_type_symbol(node.receiver_type)
ret_info := ret_sym.info as table.Array ret_info := ret_sym.info as ast.Array
ret_elem_type := g.typ(ret_info.elem_type) ret_elem_type := g.typ(ret_info.elem_type)
inp_info := inp_sym.info as table.Array inp_info := inp_sym.info as ast.Array
inp_elem_type := g.typ(inp_info.elem_type) inp_elem_type := g.typ(inp_info.elem_type)
if inp_sym.kind != .array { if inp_sym.kind != .array {
verror('map() requires an array') verror('map() requires an array')
@ -209,7 +208,7 @@ fn (mut g Gen) gen_array_sort(node ast.CallExpr) {
// println(rec_sym.kind) // println(rec_sym.kind)
verror('.sort() is an array method') verror('.sort() is an array method')
} }
info := rec_sym.info as table.Array info := rec_sym.info as ast.Array
// No arguments means we are sorting an array of builtins (e.g. `numbers.sort()`) // No arguments means we are sorting an array of builtins (e.g. `numbers.sort()`)
// The type for the comparison fns is the type of the element itself. // The type for the comparison fns is the type of the element itself.
mut typ := info.elem_type mut typ := info.elem_type
@ -228,10 +227,10 @@ fn (mut g Gen) gen_array_sort(node ast.CallExpr) {
if is_default { if is_default {
// users.sort() or users.sort(a > b) // users.sort() or users.sort(a > b)
compare_fn = match typ { compare_fn = match typ {
table.int_type, table.int_type.to_ptr() { 'compare_ints' } ast.int_type, ast.int_type.to_ptr() { 'compare_ints' }
table.u64_type, table.u64_type.to_ptr() { 'compare_u64s' } ast.u64_type, ast.u64_type.to_ptr() { 'compare_u64s' }
table.string_type, table.string_type.to_ptr() { 'compare_strings' } ast.string_type, ast.string_type.to_ptr() { 'compare_strings' }
table.f64_type, table.f64_type.to_ptr() { 'compare_floats' } ast.f64_type, ast.f64_type.to_ptr() { 'compare_floats' }
else { '' } else { '' }
} }
if compare_fn != '' && is_reverse { if compare_fn != '' && is_reverse {
@ -248,7 +247,7 @@ fn (mut g Gen) gen_array_sort(node ast.CallExpr) {
compare_fn += '_reverse' compare_fn += '_reverse'
} }
// Register a new custom `compare_xxx` function for qsort() // Register a new custom `compare_xxx` function for qsort()
g.table.register_fn(name: compare_fn, return_type: table.int_type) g.table.register_fn(name: compare_fn, return_type: ast.int_type)
infix_expr := node.args[0].expr as ast.InfixExpr infix_expr := node.args[0].expr as ast.InfixExpr
// Variables `a` and `b` are used in the `.sort(a < b)` syntax, so we can reuse them // Variables `a` and `b` are used in the `.sort(a < b)` syntax, so we can reuse them
// when generating the function as long as the args are named the same. // when generating the function as long as the args are named the same.
@ -270,7 +269,7 @@ fn (mut g Gen) gen_array_sort(node ast.CallExpr) {
g.definitions.writeln('$field_type a_ = $left_expr_str;') g.definitions.writeln('$field_type a_ = $left_expr_str;')
g.definitions.writeln('$field_type b_ = $right_expr_str;') g.definitions.writeln('$field_type b_ = $right_expr_str;')
mut op1, mut op2 := '', '' mut op1, mut op2 := '', ''
if infix_expr.left_type == table.string_type { if infix_expr.left_type == ast.string_type {
if is_reverse { if is_reverse {
op1 = 'string_gt(a_, b_)' op1 = 'string_gt(a_, b_)'
op2 = 'string_lt(a_, b_)' op2 = 'string_lt(a_, b_)'
@ -316,7 +315,7 @@ fn (mut g Gen) gen_array_filter(node ast.CallExpr) {
if sym.kind != .array { if sym.kind != .array {
verror('filter() requires an array') verror('filter() requires an array')
} }
info := sym.info as table.Array info := sym.info as ast.Array
styp := g.typ(node.return_type) styp := g.typ(node.return_type)
elem_type_str := g.typ(info.elem_type) elem_type_str := g.typ(info.elem_type)
g.empty_line = true g.empty_line = true
@ -379,7 +378,7 @@ fn (mut g Gen) gen_array_filter(node ast.CallExpr) {
// `nums.insert(0, 2)` `nums.insert(0, [2,3,4])` // `nums.insert(0, 2)` `nums.insert(0, [2,3,4])`
fn (mut g Gen) gen_array_insert(node ast.CallExpr) { fn (mut g Gen) gen_array_insert(node ast.CallExpr) {
left_sym := g.table.get_type_symbol(node.left_type) left_sym := g.table.get_type_symbol(node.left_type)
left_info := left_sym.info as table.Array left_info := left_sym.info as ast.Array
elem_type_str := g.typ(left_info.elem_type) elem_type_str := g.typ(left_info.elem_type)
arg2_sym := g.table.get_type_symbol(node.args[1].typ) arg2_sym := g.table.get_type_symbol(node.args[1].typ)
is_arg2_array := arg2_sym.kind == .array && node.args[1].typ == node.left_type is_arg2_array := arg2_sym.kind == .array && node.args[1].typ == node.left_type
@ -399,11 +398,11 @@ fn (mut g Gen) gen_array_insert(node ast.CallExpr) {
g.write('.len)') g.write('.len)')
} else { } else {
g.write(', &($elem_type_str[]){') g.write(', &($elem_type_str[]){')
if left_info.elem_type == table.string_type { if left_info.elem_type == ast.string_type {
g.write('string_clone(') g.write('string_clone(')
} }
g.expr(node.args[1].expr) g.expr(node.args[1].expr)
if left_info.elem_type == table.string_type { if left_info.elem_type == ast.string_type {
g.write(')') g.write(')')
} }
g.write('})') g.write('})')
@ -413,7 +412,7 @@ fn (mut g Gen) gen_array_insert(node ast.CallExpr) {
// `nums.prepend(2)` `nums.prepend([2,3,4])` // `nums.prepend(2)` `nums.prepend([2,3,4])`
fn (mut g Gen) gen_array_prepend(node ast.CallExpr) { fn (mut g Gen) gen_array_prepend(node ast.CallExpr) {
left_sym := g.table.get_type_symbol(node.left_type) left_sym := g.table.get_type_symbol(node.left_type)
left_info := left_sym.info as table.Array left_info := left_sym.info as ast.Array
elem_type_str := g.typ(left_info.elem_type) elem_type_str := g.typ(left_info.elem_type)
arg_sym := g.table.get_type_symbol(node.args[0].typ) arg_sym := g.table.get_type_symbol(node.args[0].typ)
is_arg_array := arg_sym.kind == .array && node.args[0].typ == node.left_type is_arg_array := arg_sym.kind == .array && node.args[0].typ == node.left_type
@ -436,12 +435,12 @@ fn (mut g Gen) gen_array_prepend(node ast.CallExpr) {
} }
} }
fn (mut g Gen) gen_array_contains_method(left_type table.Type) string { fn (mut g Gen) gen_array_contains_method(left_type ast.Type) string {
mut left_sym := g.table.get_type_symbol(left_type) mut left_sym := g.table.get_type_symbol(left_type)
mut left_type_str := g.typ(left_type).replace('*', '') mut left_type_str := g.typ(left_type).replace('*', '')
fn_name := '${left_type_str}_contains' fn_name := '${left_type_str}_contains'
if !left_sym.has_method('contains') { if !left_sym.has_method('contains') {
left_info := left_sym.info as table.Array left_info := left_sym.info as ast.Array
mut elem_type_str := g.typ(left_info.elem_type) mut elem_type_str := g.typ(left_info.elem_type)
elem_sym := g.table.get_type_symbol(left_info.elem_type) elem_sym := g.table.get_type_symbol(left_info.elem_type)
if elem_sym.kind == .function { if elem_sym.kind == .function {
@ -474,11 +473,11 @@ fn (mut g Gen) gen_array_contains_method(left_type table.Type) string {
fn_builder.writeln('\treturn false;') fn_builder.writeln('\treturn false;')
fn_builder.writeln('}') fn_builder.writeln('}')
g.auto_fn_definitions << fn_builder.str() g.auto_fn_definitions << fn_builder.str()
left_sym.register_method(&table.Fn{ left_sym.register_method(&ast.Fn{
name: 'contains' name: 'contains'
params: [table.Param{ params: [ast.Param{
typ: left_type typ: left_type
}, table.Param{ }, ast.Param{
typ: left_info.elem_type typ: left_info.elem_type
}] }]
}) })
@ -499,12 +498,12 @@ fn (mut g Gen) gen_array_contains(node ast.CallExpr) {
g.write(')') g.write(')')
} }
fn (mut g Gen) gen_array_index_method(left_type table.Type) string { fn (mut g Gen) gen_array_index_method(left_type ast.Type) string {
mut left_sym := g.table.get_type_symbol(left_type) mut left_sym := g.table.get_type_symbol(left_type)
mut left_type_str := g.typ(left_type).trim('*') mut left_type_str := g.typ(left_type).trim('*')
fn_name := '${left_type_str}_index' fn_name := '${left_type_str}_index'
if !left_sym.has_method('index') { if !left_sym.has_method('index') {
info := left_sym.info as table.Array info := left_sym.info as ast.Array
mut elem_type_str := g.typ(info.elem_type) mut elem_type_str := g.typ(info.elem_type)
elem_sym := g.table.get_type_symbol(info.elem_type) elem_sym := g.table.get_type_symbol(info.elem_type)
if elem_sym.kind == .function { if elem_sym.kind == .function {
@ -537,11 +536,11 @@ fn (mut g Gen) gen_array_index_method(left_type table.Type) string {
fn_builder.writeln('\treturn -1;') fn_builder.writeln('\treturn -1;')
fn_builder.writeln('}') fn_builder.writeln('}')
g.auto_fn_definitions << fn_builder.str() g.auto_fn_definitions << fn_builder.str()
left_sym.register_method(&table.Fn{ left_sym.register_method(&ast.Fn{
name: 'index' name: 'index'
params: [table.Param{ params: [ast.Param{
typ: left_type typ: left_type
}, table.Param{ }, ast.Param{
typ: info.elem_type typ: info.elem_type
}] }]
}) })
@ -578,7 +577,7 @@ fn (mut g Gen) gen_array_any(node ast.CallExpr) {
tmp := g.new_tmp_var() tmp := g.new_tmp_var()
s := g.go_before_stmt(0) s := g.go_before_stmt(0)
sym := g.table.get_type_symbol(node.left_type) sym := g.table.get_type_symbol(node.left_type)
info := sym.info as table.Array info := sym.info as ast.Array
// styp := g.typ(node.return_type) // styp := g.typ(node.return_type)
elem_type_str := g.typ(info.elem_type) elem_type_str := g.typ(info.elem_type)
g.empty_line = true g.empty_line = true
@ -642,7 +641,7 @@ fn (mut g Gen) gen_array_all(node ast.CallExpr) {
tmp := g.new_tmp_var() tmp := g.new_tmp_var()
s := g.go_before_stmt(0) s := g.go_before_stmt(0)
sym := g.table.get_type_symbol(node.left_type) sym := g.table.get_type_symbol(node.left_type)
info := sym.info as table.Array info := sym.info as ast.Array
// styp := g.typ(node.return_type) // styp := g.typ(node.return_type)
elem_type_str := g.typ(info.elem_type) elem_type_str := g.typ(info.elem_type)
g.empty_line = true g.empty_line = true

View File

@ -4,7 +4,6 @@
module c module c
import v.ast import v.ast
import v.table
fn (mut g Gen) gen_assert_stmt(original_assert_statement ast.AssertStmt) { fn (mut g Gen) gen_assert_stmt(original_assert_statement ast.AssertStmt) {
mut node := original_assert_statement mut node := original_assert_statement
@ -84,7 +83,7 @@ fn (mut g Gen) gen_assert_metainfo(node ast.AssertStmt) string {
return metaname return metaname
} }
fn (mut g Gen) gen_assert_single_expr(expr ast.Expr, typ table.Type) { fn (mut g Gen) gen_assert_single_expr(expr ast.Expr, typ ast.Type) {
unknown_value := '*unknown value*' unknown_value := '*unknown value*'
match expr { match expr {
ast.CastExpr, ast.IndexExpr, ast.MatchExpr { ast.CastExpr, ast.IndexExpr, ast.MatchExpr {
@ -100,7 +99,7 @@ fn (mut g Gen) gen_assert_single_expr(expr ast.Expr, typ table.Type) {
g.gen_expr_to_string(expr, typ) g.gen_expr_to_string(expr, typ)
} }
} }
ast.Type { ast.TypeNode {
sym := g.table.get_type_symbol(typ) sym := g.table.get_type_symbol(typ)
g.write(ctoslit('$sym.name')) g.write(ctoslit('$sym.name'))
} }

View File

@ -3,9 +3,9 @@
module c module c
import strings import strings
import v.table import v.ast
fn (mut g Gen) gen_sumtype_equality_fn(left table.Type) string { fn (mut g Gen) gen_sumtype_equality_fn(left ast.Type) string {
ptr_typ := g.typ(left).trim('*') ptr_typ := g.typ(left).trim('*')
if ptr_typ in g.sumtype_fn_definitions { if ptr_typ in g.sumtype_fn_definitions {
return ptr_typ return ptr_typ
@ -58,7 +58,7 @@ fn (mut g Gen) gen_sumtype_equality_fn(left table.Type) string {
return ptr_typ return ptr_typ
} }
fn (mut g Gen) gen_struct_equality_fn(left table.Type) string { fn (mut g Gen) gen_struct_equality_fn(left ast.Type) string {
ptr_typ := g.typ(left).trim('*') ptr_typ := g.typ(left).trim('*')
if ptr_typ in g.struct_fn_definitions { if ptr_typ in g.struct_fn_definitions {
return ptr_typ return ptr_typ
@ -115,14 +115,14 @@ fn (mut g Gen) gen_struct_equality_fn(left table.Type) string {
return ptr_typ return ptr_typ
} }
fn (mut g Gen) gen_alias_equality_fn(left table.Type) string { fn (mut g Gen) gen_alias_equality_fn(left ast.Type) string {
ptr_typ := g.typ(left).trim('*') ptr_typ := g.typ(left).trim('*')
if ptr_typ in g.alias_fn_definitions { if ptr_typ in g.alias_fn_definitions {
return ptr_typ return ptr_typ
} }
g.alias_fn_definitions << ptr_typ g.alias_fn_definitions << ptr_typ
left_sym := g.table.get_type_symbol(left) left_sym := g.table.get_type_symbol(left)
info := left_sym.info as table.Alias info := left_sym.info as ast.Alias
g.type_definitions.writeln('static bool ${ptr_typ}_alias_eq($ptr_typ a, $ptr_typ b); // auto') g.type_definitions.writeln('static bool ${ptr_typ}_alias_eq($ptr_typ a, $ptr_typ b); // auto')
mut fn_builder := strings.new_builder(512) mut fn_builder := strings.new_builder(512)
fn_builder.writeln('static bool ${ptr_typ}_alias_eq($ptr_typ a, $ptr_typ b) {') fn_builder.writeln('static bool ${ptr_typ}_alias_eq($ptr_typ a, $ptr_typ b) {')
@ -157,7 +157,7 @@ fn (mut g Gen) gen_alias_equality_fn(left table.Type) string {
return ptr_typ return ptr_typ
} }
fn (mut g Gen) gen_array_equality_fn(left table.Type) string { fn (mut g Gen) gen_array_equality_fn(left ast.Type) string {
ptr_typ := g.typ(left).trim('*') ptr_typ := g.typ(left).trim('*')
if ptr_typ in g.array_fn_definitions { if ptr_typ in g.array_fn_definitions {
return ptr_typ return ptr_typ
@ -209,7 +209,7 @@ fn (mut g Gen) gen_array_equality_fn(left table.Type) string {
return ptr_typ return ptr_typ
} }
fn (mut g Gen) gen_fixed_array_equality_fn(left table.Type) string { fn (mut g Gen) gen_fixed_array_equality_fn(left ast.Type) string {
ptr_typ := g.typ(left).trim('*') ptr_typ := g.typ(left).trim('*')
if ptr_typ in g.array_fn_definitions { if ptr_typ in g.array_fn_definitions {
return ptr_typ return ptr_typ
@ -259,7 +259,7 @@ fn (mut g Gen) gen_fixed_array_equality_fn(left table.Type) string {
return ptr_typ return ptr_typ
} }
fn (mut g Gen) gen_map_equality_fn(left table.Type) string { fn (mut g Gen) gen_map_equality_fn(left ast.Type) string {
ptr_typ := g.typ(left).trim('*') ptr_typ := g.typ(left).trim('*')
if ptr_typ in g.map_fn_definitions { if ptr_typ in g.map_fn_definitions {
return ptr_typ return ptr_typ
@ -281,7 +281,7 @@ fn (mut g Gen) gen_map_equality_fn(left table.Type) string {
kind := g.table.type_kind(value_typ) kind := g.table.type_kind(value_typ)
if kind == .function { if kind == .function {
value_sym := g.table.get_type_symbol(value_typ) value_sym := g.table.get_type_symbol(value_typ)
func := value_sym.info as table.FnType func := value_sym.info as ast.FnType
ret_styp := g.typ(func.func.return_type) ret_styp := g.typ(func.func.return_type)
fn_builder.write_string('\t\t$ret_styp (*v) (') fn_builder.write_string('\t\t$ret_styp (*v) (')
arg_len := func.func.params.len arg_len := func.func.params.len

View File

@ -2,26 +2,26 @@
// Use of this source code is governed by an MIT license that can be found in the LICENSE file. // Use of this source code is governed by an MIT license that can be found in the LICENSE file.
module c module c
import v.table import v.ast
import v.util import v.util
fn should_use_indent_func(kind table.Kind) bool { fn should_use_indent_func(kind ast.Kind) bool {
return kind in [.struct_, .alias, .array, .array_fixed, .map, .sum_type, .interface_] return kind in [.struct_, .alias, .array, .array_fixed, .map, .sum_type, .interface_]
} }
fn (mut g Gen) gen_str_default(sym table.TypeSymbol, styp string, str_fn_name string) { fn (mut g Gen) gen_str_default(sym ast.TypeSymbol, styp string, str_fn_name string) {
mut convertor := '' mut convertor := ''
mut typename_ := '' mut typename_ := ''
if sym.parent_idx in table.integer_type_idxs { if sym.parent_idx in ast.integer_type_idxs {
convertor = 'int' convertor = 'int'
typename_ = 'int' typename_ = 'int'
} else if sym.parent_idx == table.f32_type_idx { } else if sym.parent_idx == ast.f32_type_idx {
convertor = 'float' convertor = 'float'
typename_ = 'f32' typename_ = 'f32'
} else if sym.parent_idx == table.f64_type_idx { } else if sym.parent_idx == ast.f64_type_idx {
convertor = 'double' convertor = 'double'
typename_ = 'f64' typename_ = 'f64'
} else if sym.parent_idx == table.bool_type_idx { } else if sym.parent_idx == ast.bool_type_idx {
convertor = 'bool' convertor = 'bool'
typename_ = 'bool' typename_ = 'bool'
} else { } else {
@ -40,7 +40,7 @@ fn (mut g Gen) gen_str_default(sym table.TypeSymbol, styp string, str_fn_name st
g.auto_str_funcs.writeln('}') g.auto_str_funcs.writeln('}')
} }
fn (g &Gen) type_to_fmt(typ table.Type) string { fn (g &Gen) type_to_fmt(typ ast.Type) string {
sym := g.table.get_type_symbol(typ) sym := g.table.get_type_symbol(typ)
if typ.is_ptr() && (typ.is_int() || typ.is_float()) { if typ.is_ptr() && (typ.is_int() || typ.is_float()) {
return '%.*s\\000' return '%.*s\\000'
@ -61,11 +61,11 @@ fn (g &Gen) type_to_fmt(typ table.Type) string {
return '%d\\000' return '%d\\000'
} }
fn (mut g Gen) gen_str_for_type(typ table.Type) string { fn (mut g Gen) gen_str_for_type(typ ast.Type) string {
styp := g.typ(typ).replace('*', '') styp := g.typ(typ).replace('*', '')
mut sym := g.table.get_type_symbol(g.unwrap_generic(typ)) mut sym := g.table.get_type_symbol(g.unwrap_generic(typ))
mut str_fn_name := styp_to_str_fn_name(styp) mut str_fn_name := styp_to_str_fn_name(styp)
if mut sym.info is table.Alias { if mut sym.info is ast.Alias {
if sym.info.is_import { if sym.info.is_import {
sym = g.table.get_type_symbol(sym.info.parent_type) sym = g.table.get_type_symbol(sym.info.parent_type)
str_fn_name = styp_to_str_fn_name(sym.name) str_fn_name = styp_to_str_fn_name(sym.name)
@ -79,38 +79,38 @@ fn (mut g Gen) gen_str_for_type(typ table.Type) string {
} }
g.str_types << already_generated_key g.str_types << already_generated_key
match mut sym.info { match mut sym.info {
table.Alias { ast.Alias {
if sym.info.is_import { if sym.info.is_import {
g.gen_str_default(sym, styp, str_fn_name) g.gen_str_default(sym, styp, str_fn_name)
} else { } else {
g.gen_str_for_alias(sym.info, styp, str_fn_name) g.gen_str_for_alias(sym.info, styp, str_fn_name)
} }
} }
table.Array { ast.Array {
g.gen_str_for_array(sym.info, styp, str_fn_name) g.gen_str_for_array(sym.info, styp, str_fn_name)
} }
table.ArrayFixed { ast.ArrayFixed {
g.gen_str_for_array_fixed(sym.info, styp, str_fn_name) g.gen_str_for_array_fixed(sym.info, styp, str_fn_name)
} }
table.Enum { ast.Enum {
g.gen_str_for_enum(sym.info, styp, str_fn_name) g.gen_str_for_enum(sym.info, styp, str_fn_name)
} }
table.FnType { ast.FnType {
g.gen_str_for_fn_type(sym.info, styp, str_fn_name) g.gen_str_for_fn_type(sym.info, styp, str_fn_name)
} }
table.Struct { ast.Struct {
g.gen_str_for_struct(sym.info, styp, str_fn_name) g.gen_str_for_struct(sym.info, styp, str_fn_name)
} }
table.Map { ast.Map {
g.gen_str_for_map(sym.info, styp, str_fn_name) g.gen_str_for_map(sym.info, styp, str_fn_name)
} }
table.MultiReturn { ast.MultiReturn {
g.gen_str_for_multi_return(sym.info, styp, str_fn_name) g.gen_str_for_multi_return(sym.info, styp, str_fn_name)
} }
table.SumType { ast.SumType {
g.gen_str_for_union_sum_type(sym.info, styp, str_fn_name) g.gen_str_for_union_sum_type(sym.info, styp, str_fn_name)
} }
table.Interface { ast.Interface {
g.gen_str_for_interface(sym.info, styp, str_fn_name) g.gen_str_for_interface(sym.info, styp, str_fn_name)
} }
else { else {
@ -129,7 +129,7 @@ fn (mut g Gen) gen_str_for_type(typ table.Type) string {
return str_fn_name return str_fn_name
} }
fn (mut g Gen) gen_str_for_option(typ table.Type, styp string, str_fn_name string) { fn (mut g Gen) gen_str_for_option(typ ast.Type, styp string, str_fn_name string) {
parent_type := typ.clear_flag(.optional) parent_type := typ.clear_flag(.optional)
sym := g.table.get_type_symbol(parent_type) sym := g.table.get_type_symbol(parent_type)
sym_has_str_method, _, _ := sym.str_method_info() sym_has_str_method, _, _ := sym.str_method_info()
@ -157,7 +157,7 @@ fn (mut g Gen) gen_str_for_option(typ table.Type, styp string, str_fn_name strin
g.auto_str_funcs.writeln('}') g.auto_str_funcs.writeln('}')
} }
fn (mut g Gen) gen_str_for_alias(info table.Alias, styp string, str_fn_name string) { fn (mut g Gen) gen_str_for_alias(info ast.Alias, styp string, str_fn_name string) {
sym := g.table.get_type_symbol(info.parent_type) sym := g.table.get_type_symbol(info.parent_type)
sym_has_str_method, _, _ := sym.str_method_info() sym_has_str_method, _, _ := sym.str_method_info()
mut parent_str_fn_name := styp_to_str_fn_name(sym.name.replace('.', '__')) mut parent_str_fn_name := styp_to_str_fn_name(sym.name.replace('.', '__'))
@ -177,10 +177,10 @@ fn (mut g Gen) gen_str_for_alias(info table.Alias, styp string, str_fn_name stri
g.auto_str_funcs.writeln('}') g.auto_str_funcs.writeln('}')
} }
fn (mut g Gen) gen_str_for_array(info table.Array, styp string, str_fn_name string) { fn (mut g Gen) gen_str_for_array(info ast.Array, styp string, str_fn_name string) {
mut typ := info.elem_type mut typ := info.elem_type
mut sym := g.table.get_type_symbol(info.elem_type) mut sym := g.table.get_type_symbol(info.elem_type)
if mut sym.info is table.Alias { if mut sym.info is ast.Alias {
typ = sym.info.parent_type typ = sym.info.parent_type
sym = g.table.get_type_symbol(typ) sym = g.table.get_type_symbol(typ)
} }
@ -245,7 +245,7 @@ fn (mut g Gen) gen_str_for_array(info table.Array, styp string, str_fn_name stri
} }
} }
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, x);') g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, x);')
if g.is_autofree && typ != table.bool_type { if g.is_autofree && typ != ast.bool_type {
// no need to free "true"/"false" literals // no need to free "true"/"false" literals
g.auto_str_funcs.writeln('\t\tstring_free(&x);') g.auto_str_funcs.writeln('\t\tstring_free(&x);')
} }
@ -260,10 +260,10 @@ fn (mut g Gen) gen_str_for_array(info table.Array, styp string, str_fn_name stri
g.auto_str_funcs.writeln('}') g.auto_str_funcs.writeln('}')
} }
fn (mut g Gen) gen_str_for_array_fixed(info table.ArrayFixed, styp string, str_fn_name string) { fn (mut g Gen) gen_str_for_array_fixed(info ast.ArrayFixed, styp string, str_fn_name string) {
mut typ := info.elem_type mut typ := info.elem_type
mut sym := g.table.get_type_symbol(info.elem_type) mut sym := g.table.get_type_symbol(info.elem_type)
if mut sym.info is table.Alias { if mut sym.info is ast.Alias {
typ = sym.info.parent_type typ = sym.info.parent_type
sym = g.table.get_type_symbol(typ) sym = g.table.get_type_symbol(typ)
} }
@ -322,10 +322,10 @@ fn (mut g Gen) gen_str_for_array_fixed(info table.ArrayFixed, styp string, str_f
g.auto_str_funcs.writeln('}') g.auto_str_funcs.writeln('}')
} }
fn (mut g Gen) gen_str_for_map(info table.Map, styp string, str_fn_name string) { fn (mut g Gen) gen_str_for_map(info ast.Map, styp string, str_fn_name string) {
mut key_typ := info.key_type mut key_typ := info.key_type
mut key_sym := g.table.get_type_symbol(key_typ) mut key_sym := g.table.get_type_symbol(key_typ)
if mut key_sym.info is table.Alias { if mut key_sym.info is ast.Alias {
key_typ = key_sym.info.parent_type key_typ = key_sym.info.parent_type
key_sym = g.table.get_type_symbol(key_typ) key_sym = g.table.get_type_symbol(key_typ)
} }
@ -337,7 +337,7 @@ fn (mut g Gen) gen_str_for_map(info table.Map, styp string, str_fn_name string)
mut val_typ := info.value_type mut val_typ := info.value_type
mut val_sym := g.table.get_type_symbol(val_typ) mut val_sym := g.table.get_type_symbol(val_typ)
if mut val_sym.info is table.Alias { if mut val_sym.info is ast.Alias {
val_typ = val_sym.info.parent_type val_typ = val_sym.info.parent_type
val_sym = g.table.get_type_symbol(val_typ) val_sym = g.table.get_type_symbol(val_typ)
} }
@ -393,7 +393,7 @@ fn (mut g Gen) gen_str_for_map(info table.Map, styp string, str_fn_name string)
g.auto_str_funcs.writeln('}') g.auto_str_funcs.writeln('}')
} }
fn (mut g Gen) gen_str_for_multi_return(info table.MultiReturn, styp string, str_fn_name string) { fn (mut g Gen) gen_str_for_multi_return(info ast.MultiReturn, styp string, str_fn_name string) {
for typ in info.types { for typ in info.types {
sym := g.table.get_type_symbol(typ) sym := g.table.get_type_symbol(typ)
if !sym.has_method('str') { if !sym.has_method('str') {
@ -447,7 +447,7 @@ fn (mut g Gen) gen_str_for_multi_return(info table.MultiReturn, styp string, str
g.auto_str_funcs.writeln('}') g.auto_str_funcs.writeln('}')
} }
fn (mut g Gen) gen_str_for_struct(info table.Struct, styp string, str_fn_name string) { fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, str_fn_name string) {
// TODO: short it if possible // TODO: short it if possible
// generates all definitions of substructs // generates all definitions of substructs
mut fnames2strfunc := map{ mut fnames2strfunc := map{
@ -534,7 +534,7 @@ fn (mut g Gen) gen_str_for_struct(info table.Struct, styp string, str_fn_name st
g.auto_str_funcs.writeln('}') g.auto_str_funcs.writeln('}')
} }
fn struct_auto_str_func(sym &table.TypeSymbol, field_type table.Type, fn_name string, field_name string) string { fn struct_auto_str_func(sym &ast.TypeSymbol, field_type ast.Type, fn_name string, field_name string) string {
has_custom_str, expects_ptr, _ := sym.str_method_info() has_custom_str, expects_ptr, _ := sym.str_method_info()
if sym.kind == .enum_ { if sym.kind == .enum_ {
return '${fn_name}(it.${c_name(field_name)})' return '${fn_name}(it.${c_name(field_name)})'
@ -574,7 +574,7 @@ fn struct_auto_str_func(sym &table.TypeSymbol, field_type table.Type, fn_name st
} }
} }
fn (mut g Gen) gen_str_for_enum(info table.Enum, styp string, str_fn_name string) { fn (mut g Gen) gen_str_for_enum(info ast.Enum, styp string, str_fn_name string) {
s := util.no_dots(styp) s := util.no_dots(styp)
g.type_definitions.writeln('static string ${str_fn_name}($styp it); // auto') g.type_definitions.writeln('static string ${str_fn_name}($styp it); // auto')
g.auto_str_funcs.writeln('static string ${str_fn_name}($styp it) { /* gen_str_for_enum */') g.auto_str_funcs.writeln('static string ${str_fn_name}($styp it) { /* gen_str_for_enum */')
@ -606,7 +606,7 @@ fn (mut g Gen) gen_str_for_enum(info table.Enum, styp string, str_fn_name string
g.auto_str_funcs.writeln('}') g.auto_str_funcs.writeln('}')
} }
fn (mut g Gen) gen_str_for_interface(info table.Interface, styp string, str_fn_name string) { fn (mut g Gen) gen_str_for_interface(info ast.Interface, styp string, str_fn_name string) {
mut gen_fn_names := map[string]string{} mut gen_fn_names := map[string]string{}
for typ in info.types { for typ in info.types {
sym := g.table.get_type_symbol(typ) sym := g.table.get_type_symbol(typ)
@ -641,7 +641,7 @@ fn (mut g Gen) gen_str_for_interface(info table.Interface, styp string, str_fn_n
func_name = 'indent_$func_name' func_name = 'indent_$func_name'
} }
deref := if sym_has_str_method && str_method_expects_ptr { ' ' } else { '*' } deref := if sym_has_str_method && str_method_expects_ptr { ' ' } else { '*' }
value_fmt := if typ == table.string_type { "'%.*s\\000'" } else { '%.*s\\000' } value_fmt := if typ == ast.string_type { "'%.*s\\000'" } else { '%.*s\\000' }
g.auto_str_funcs.write_string('\tif (x._interface_idx == _${styp}_${subtype.cname}_index)') g.auto_str_funcs.write_string('\tif (x._interface_idx == _${styp}_${subtype.cname}_index)')
g.auto_str_funcs.write_string(' return _STR("${clean_interface_v_type_name}($value_fmt)", 2, ') g.auto_str_funcs.write_string(' return _STR("${clean_interface_v_type_name}($value_fmt)", 2, ')
@ -655,7 +655,7 @@ fn (mut g Gen) gen_str_for_interface(info table.Interface, styp string, str_fn_n
g.auto_str_funcs.writeln('}') g.auto_str_funcs.writeln('}')
} }
fn (mut g Gen) gen_str_for_union_sum_type(info table.SumType, styp string, str_fn_name string) { fn (mut g Gen) gen_str_for_union_sum_type(info ast.SumType, styp string, str_fn_name string) {
mut gen_fn_names := map[string]string{} mut gen_fn_names := map[string]string{}
for typ in info.variants { for typ in info.variants {
sym := g.table.get_type_symbol(typ) sym := g.table.get_type_symbol(typ)
@ -678,7 +678,7 @@ fn (mut g Gen) gen_str_for_union_sum_type(info table.SumType, styp string, str_f
g.auto_str_funcs.writeln('\tswitch(x._typ) {') g.auto_str_funcs.writeln('\tswitch(x._typ) {')
for typ in info.variants { for typ in info.variants {
mut value_fmt := '%.*s\\000' mut value_fmt := '%.*s\\000'
if typ == table.string_type { if typ == ast.string_type {
value_fmt = "'$value_fmt'" value_fmt = "'$value_fmt'"
} }
typ_str := g.typ(typ) typ_str := g.typ(typ)
@ -704,7 +704,7 @@ fn (mut g Gen) gen_str_for_union_sum_type(info table.SumType, styp string, str_f
g.auto_str_funcs.writeln('}') g.auto_str_funcs.writeln('}')
} }
fn (mut g Gen) fn_decl_str(info table.FnType) string { fn (mut g Gen) fn_decl_str(info ast.FnType) string {
mut fn_str := 'fn (' mut fn_str := 'fn ('
for i, arg in info.func.params { for i, arg in info.func.params {
if i > 0 { if i > 0 {
@ -713,13 +713,13 @@ fn (mut g Gen) fn_decl_str(info table.FnType) string {
fn_str += util.strip_main_name(g.table.get_type_name(arg.typ)) fn_str += util.strip_main_name(g.table.get_type_name(arg.typ))
} }
fn_str += ')' fn_str += ')'
if info.func.return_type != table.void_type { if info.func.return_type != ast.void_type {
fn_str += ' ${util.strip_main_name(g.table.get_type_name(info.func.return_type))}' fn_str += ' ${util.strip_main_name(g.table.get_type_name(info.func.return_type))}'
} }
return fn_str return fn_str
} }
fn (mut g Gen) gen_str_for_fn_type(info table.FnType, styp string, str_fn_name string) { fn (mut g Gen) gen_str_for_fn_type(info ast.FnType, styp string, str_fn_name string) {
g.type_definitions.writeln('static string ${str_fn_name}(); // auto') g.type_definitions.writeln('static string ${str_fn_name}(); // auto')
g.auto_str_funcs.writeln('static string ${str_fn_name}() { return _SLIT("${g.fn_decl_str(info)}");}') g.auto_str_funcs.writeln('static string ${str_fn_name}() { return _SLIT("${g.fn_decl_str(info)}");}')
} }

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,6 @@ module c
import os import os
import v.ast import v.ast
import v.table
import v.util import v.util
fn (mut g Gen) comptime_selector(node ast.ComptimeSelector) { fn (mut g Gen) comptime_selector(node ast.ComptimeSelector) {
@ -123,7 +122,7 @@ fn (mut g Gen) comptime_call(node ast.ComptimeCall) {
} else { } else {
// last argument; try to expand if it's []string // last argument; try to expand if it's []string
idx := i - node.args.len idx := i - node.args.len
if m.params[i].typ.is_int() || m.params[i].typ.idx() == table.bool_type_idx { if m.params[i].typ.is_int() || m.params[i].typ.idx() == ast.bool_type_idx {
// Gets the type name and cast the string to the type with the string_<type> function // Gets the type name and cast the string to the type with the string_<type> function
type_name := g.table.type_symbols[int(m.params[i].typ)].str() type_name := g.table.type_symbols[int(m.params[i].typ)].str()
g.write('string_${type_name}(((string*)${node.args[node.args.len - 1]}.data) [$idx])') g.write('string_${type_name}(((string*)${node.args[node.args.len - 1]}.data) [$idx])')
@ -140,7 +139,7 @@ fn (mut g Gen) comptime_call(node ast.ComptimeCall) {
} }
mut j := 0 mut j := 0
for method in node.sym.methods { for method in node.sym.methods {
// if method.return_type != table.void_type { // if method.return_type != ast.void_type {
if method.return_type != node.result_type { if method.return_type != node.result_type {
continue continue
} }
@ -165,7 +164,7 @@ fn (mut g Gen) comptime_call(node ast.ComptimeCall) {
} }
} }
fn cgen_attrs(attrs []table.Attr) []string { fn cgen_attrs(attrs []ast.Attr) []string {
mut res := []string{cap: attrs.len} mut res := []string{cap: attrs.len}
for attr in attrs { for attr in attrs {
// we currently don't quote 'arg' (otherwise we could just use `s := attr.str()`) // we currently don't quote 'arg' (otherwise we could just use `s := attr.str()`)
@ -287,12 +286,12 @@ fn (mut g Gen) comp_if_cond(cond ast.Expr) bool {
.key_is, .not_is { .key_is, .not_is {
left := cond.left left := cond.left
mut name := '' mut name := ''
mut exp_type := table.Type(0) mut exp_type := ast.Type(0)
got_type := (cond.right as ast.Type).typ got_type := (cond.right as ast.TypeNode).typ
if left is ast.SelectorExpr { if left is ast.SelectorExpr {
name = '${left.expr}.$left.field_name' name = '${left.expr}.$left.field_name'
exp_type = g.comptime_var_type_map[name] exp_type = g.comptime_var_type_map[name]
} else if left is ast.Type { } else if left is ast.TypeNode {
name = left.str() name = left.str()
// this is only allowed for generics currently, otherwise blocked by checker // this is only allowed for generics currently, otherwise blocked by checker
exp_type = g.unwrap_generic(left.typ) exp_type = g.unwrap_generic(left.typ)
@ -333,7 +332,7 @@ fn (mut g Gen) comp_for(node ast.CompFor) {
sym := g.table.get_type_symbol(g.unwrap_generic(node.typ)) sym := g.table.get_type_symbol(g.unwrap_generic(node.typ))
g.writeln('/* \$for $node.val_var in ${sym.name}($node.kind.str()) */ {') g.writeln('/* \$for $node.val_var in ${sym.name}($node.kind.str()) */ {')
g.indent++ g.indent++
// vweb_result_type := table.new_type(g.table.find_type_idx('vweb.Result')) // vweb_result_type := ast.new_type(g.table.find_type_idx('vweb.Result'))
mut i := 0 mut i := 0
// g.writeln('string method = _SLIT("");') // g.writeln('string method = _SLIT("");')
if node.kind == .methods { if node.kind == .methods {
@ -345,7 +344,7 @@ fn (mut g Gen) comp_for(node ast.CompFor) {
} }
for method in methods { // sym.methods { for method in methods { // sym.methods {
/* /*
if method.return_type != vweb_result_type { // table.void_type { if method.return_type != vweb_result_type { // ast.void_type {
continue continue
} }
*/ */
@ -414,7 +413,7 @@ fn (mut g Gen) comp_for(node ast.CompFor) {
} }
} else if node.kind == .fields { } else if node.kind == .fields {
// TODO add fields // TODO add fields
if sym.info is table.Struct { if sym.info is ast.Struct {
mut fields := sym.info.fields.filter(it.attrs.len == 0) mut fields := sym.info.fields.filter(it.attrs.len == 0)
fields_with_attrs := sym.info.fields.filter(it.attrs.len > 0) fields_with_attrs := sym.info.fields.filter(it.attrs.len > 0)
fields << fields_with_attrs fields << fields_with_attrs

View File

@ -1,9 +1,8 @@
module c module c
import v.ast import v.ast
import v.table
fn (mut g Gen) new_ctemp_var(expr ast.Expr, expr_type table.Type) ast.CTempVar { fn (mut g Gen) new_ctemp_var(expr ast.Expr, expr_type ast.Type) ast.CTempVar {
return ast.CTempVar{ return ast.CTempVar{
name: g.new_tmp_var() name: g.new_tmp_var()
typ: expr_type typ: expr_type
@ -12,7 +11,7 @@ fn (mut g Gen) new_ctemp_var(expr ast.Expr, expr_type table.Type) ast.CTempVar {
} }
} }
fn (mut g Gen) new_ctemp_var_then_gen(expr ast.Expr, expr_type table.Type) ast.CTempVar { fn (mut g Gen) new_ctemp_var_then_gen(expr ast.Expr, expr_type ast.Type) ast.CTempVar {
x := g.new_ctemp_var(expr, expr_type) x := g.new_ctemp_var(expr, expr_type)
g.gen_ctemp_var(x) g.gen_ctemp_var(x)
return x return x

View File

@ -1,7 +1,6 @@
module c module c
import v.ast import v.ast
import v.table
fn (mut g Gen) dump_expr(node ast.DumpExpr) { fn (mut g Gen) dump_expr(node ast.DumpExpr) {
sexpr := ctoslit(node.expr.str()) sexpr := ctoslit(node.expr.str())
@ -20,7 +19,7 @@ fn (mut g Gen) dump_expr(node ast.DumpExpr) {
fn (mut g Gen) dump_expr_definitions() { fn (mut g Gen) dump_expr_definitions() {
if g.pref.build_mode == .build_module { if g.pref.build_mode == .build_module {
for dump_type, cname in g.table.dumps { for dump_type, cname in g.table.dumps {
is_ptr := table.Type(dump_type).is_ptr() is_ptr := ast.Type(dump_type).is_ptr()
ptr_suffix := if is_ptr { '*' } else { '' } ptr_suffix := if is_ptr { '*' } else { '' }
dump_fn_name := '_v_dump_expr_$cname' + (if is_ptr { '_ptr' } else { '' }) dump_fn_name := '_v_dump_expr_$cname' + (if is_ptr { '_ptr' } else { '' })
g.definitions.writeln('$cname$ptr_suffix ${dump_fn_name}(string fpath, int line, string sexpr, $cname$ptr_suffix x) {') g.definitions.writeln('$cname$ptr_suffix ${dump_fn_name}(string fpath, int line, string sexpr, $cname$ptr_suffix x) {')
@ -28,7 +27,7 @@ fn (mut g Gen) dump_expr_definitions() {
} else { } else {
for dump_type, cname in g.table.dumps { for dump_type, cname in g.table.dumps {
to_string_fn_name := g.gen_str_for_type(dump_type) to_string_fn_name := g.gen_str_for_type(dump_type)
is_ptr := table.Type(dump_type).is_ptr() is_ptr := ast.Type(dump_type).is_ptr()
ptr_astarisk := if is_ptr { '*' } else { '' } ptr_astarisk := if is_ptr { '*' } else { '' }
dump_fn_name := '_v_dump_expr_$cname' + (if is_ptr { '_ptr' } else { '' }) dump_fn_name := '_v_dump_expr_$cname' + (if is_ptr { '_ptr' } else { '' })
g.definitions.writeln('$cname$ptr_astarisk ${dump_fn_name}(string fpath, int line, string sexpr, $cname$ptr_astarisk x) {') g.definitions.writeln('$cname$ptr_astarisk ${dump_fn_name}(string fpath, int line, string sexpr, $cname$ptr_astarisk x) {')

View File

@ -30,7 +30,7 @@ fn (mut g Gen) gen_embed_file_init(node ast.ComptimeCall) {
g.writeln('} // \$embed_file("$node.embed_file.apath")') g.writeln('} // \$embed_file("$node.embed_file.apath")')
} }
// gen_embedded_data embeds data into the V target executable. // gen_embedded_data embeds data into the V target execuast.
fn (mut g Gen) gen_embedded_data() { fn (mut g Gen) gen_embedded_data() {
/* /*
TODO implement compression. TODO implement compression.

View File

@ -4,7 +4,6 @@
module c module c
import v.ast import v.ast
import v.table
import v.util import v.util
fn (mut g Gen) is_used_by_main(node ast.FnDecl) bool { fn (mut g Gen) is_used_by_main(node ast.FnDecl) bool {
@ -302,7 +301,7 @@ fn (mut g Gen) gen_fn_decl(node ast.FnDecl, skip bool) {
} else { } else {
g.defer_stmts = [] g.defer_stmts = []
} }
if node.return_type != table.void_type && node.stmts.len > 0 && node.stmts.last() !is ast.Return { if node.return_type != ast.void_type && node.stmts.len > 0 && node.stmts.last() !is ast.Return {
default_expr := g.type_default(node.return_type) default_expr := g.type_default(node.return_type)
// TODO: perf? // TODO: perf?
if default_expr == '{0}' { if default_expr == '{0}' {
@ -353,7 +352,7 @@ fn (mut g Gen) write_defer_stmts_when_needed() {
} }
// fn decl args // fn decl args
fn (mut g Gen) fn_args(args []table.Param, is_variadic bool) ([]string, []string) { fn (mut g Gen) fn_args(args []ast.Param, is_variadic bool) ([]string, []string) {
mut fargs := []string{} mut fargs := []string{}
mut fargtypes := []string{} mut fargtypes := []string{}
if args.len == 0 { if args.len == 0 {
@ -366,7 +365,7 @@ fn (mut g Gen) fn_args(args []table.Param, is_variadic bool) ([]string, []string
arg_type_sym := g.table.get_type_symbol(typ) arg_type_sym := g.table.get_type_symbol(typ)
mut arg_type_name := g.typ(typ) // util.no_dots(arg_type_sym.name) mut arg_type_name := g.typ(typ) // util.no_dots(arg_type_sym.name)
if arg_type_sym.kind == .function { if arg_type_sym.kind == .function {
info := arg_type_sym.info as table.FnType info := arg_type_sym.info as ast.FnType
func := info.func func := info.func
if !info.is_anon { if !info.is_anon {
g.write(arg_type_name + ' ' + caname) g.write(arg_type_name + ' ' + caname)
@ -449,7 +448,7 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
if is_gen_or_and_assign_rhs { if is_gen_or_and_assign_rhs {
unwrapped_typ := node.return_type.clear_flag(.optional) unwrapped_typ := node.return_type.clear_flag(.optional)
unwrapped_styp := g.typ(unwrapped_typ) unwrapped_styp := g.typ(unwrapped_typ)
if unwrapped_typ == table.void_type { if unwrapped_typ == ast.void_type {
g.write('\n $cur_line') g.write('\n $cur_line')
} else if g.table.get_type_symbol(node.return_type).kind == .multi_return { } else if g.table.get_type_symbol(node.return_type).kind == .multi_return {
g.write('\n $cur_line $tmp_opt /*U*/') g.write('\n $cur_line $tmp_opt /*U*/')
@ -462,7 +461,7 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
} }
} }
pub fn (g &Gen) unwrap_generic(typ table.Type) table.Type { pub fn (g &Gen) unwrap_generic(typ ast.Type) ast.Type {
if typ.has_flag(.generic) { if typ.has_flag(.generic) {
sym := g.table.get_type_symbol(typ) sym := g.table.get_type_symbol(typ)
for i, generic_param in g.cur_fn.generic_params { for i, generic_param in g.cur_fn.generic_params {
@ -486,7 +485,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
typ_sym := g.table.get_type_symbol(unwrapped_rec_type) typ_sym := g.table.get_type_symbol(unwrapped_rec_type)
rec_cc_type := g.cc_type(unwrapped_rec_type, false) rec_cc_type := g.cc_type(unwrapped_rec_type, false)
mut receiver_type_name := util.no_dots(rec_cc_type) mut receiver_type_name := util.no_dots(rec_cc_type)
if typ_sym.kind == .interface_ && (typ_sym.info as table.Interface).defines_method(node.name) { if typ_sym.kind == .interface_ && (typ_sym.info as ast.Interface).defines_method(node.name) {
// Speaker_name_table[s._interface_idx].speak(s._object) // Speaker_name_table[s._interface_idx].speak(s._object)
$if debug_interface_method_call ? { $if debug_interface_method_call ? {
eprintln('>>> interface typ_sym.name: $typ_sym.name | receiver_type_name: $receiver_type_name') eprintln('>>> interface typ_sym.name: $typ_sym.name | receiver_type_name: $receiver_type_name')
@ -628,7 +627,7 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
} }
} }
for i, generic_type in node.generic_types { for i, generic_type in node.generic_types {
if generic_type != table.void_type && generic_type != 0 { if generic_type != ast.void_type && generic_type != 0 {
// Using _T_ to differentiate between get<string> and get_string // Using _T_ to differentiate between get<string> and get_string
// `foo<int>()` => `foo_T_int()` // `foo<int>()` => `foo_T_int()`
if i == 0 { if i == 0 {
@ -767,7 +766,7 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
g.writeln('string $tmp2 = json__json_print_pretty($json_obj);') g.writeln('string $tmp2 = json__json_print_pretty($json_obj);')
} }
} else { } else {
ast_type := node.args[0].expr as ast.Type ast_type := node.args[0].expr as ast.TypeNode
// `json.decode(User, s)` => json.decode_User(s) // `json.decode(User, s)` => json.decode_User(s)
typ := c_name(g.typ(ast_type.typ)) typ := c_name(g.typ(ast_type.typ))
fn_name := c_name(name) + '_' + typ fn_name := c_name(name) + '_' + typ
@ -818,18 +817,18 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
// g.generate_tmp_autofree_arg_vars(node, name) // g.generate_tmp_autofree_arg_vars(node, name)
// Handle `print(x)` // Handle `print(x)`
mut print_auto_str := false mut print_auto_str := false
if is_print && node.args[0].typ != table.string_type { // && !free_tmp_arg_vars { if is_print && node.args[0].typ != ast.string_type { // && !free_tmp_arg_vars {
mut typ := node.args[0].typ mut typ := node.args[0].typ
if typ == 0 { if typ == 0 {
g.checker_bug('print arg.typ is 0', node.pos) g.checker_bug('print arg.typ is 0', node.pos)
} }
mut sym := g.table.get_type_symbol(typ) mut sym := g.table.get_type_symbol(typ)
if mut sym.info is table.Alias { if mut sym.info is ast.Alias {
typ = sym.info.parent_type typ = sym.info.parent_type
sym = g.table.get_type_symbol(typ) sym = g.table.get_type_symbol(typ)
} }
// check if alias parent also not a string // check if alias parent also not a string
if typ != table.string_type { if typ != ast.string_type {
expr := node.args[0].expr expr := node.args[0].expr
if g.is_autofree && !typ.has_flag(.optional) { if g.is_autofree && !typ.has_flag(.optional) {
// Create a temporary variable so that the value can be freed // Create a temporary variable so that the value can be freed
@ -930,7 +929,7 @@ fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) {
} else { } else {
scope.register(ast.Var{ scope.register(ast.Var{
name: t name: t
typ: table.string_type typ: ast.string_type
is_autofree_tmp: true is_autofree_tmp: true
pos: node.pos pos: node.pos
}) })
@ -1009,7 +1008,7 @@ fn (mut g Gen) call_args(node ast.CallExpr) {
if is_variadic && i == expected_types.len - 1 { if is_variadic && i == expected_types.len - 1 {
break break
} }
use_tmp_var_autofree := g.is_autofree && arg.typ == table.string_type && arg.is_tmp_autofree use_tmp_var_autofree := g.is_autofree && arg.typ == ast.string_type && arg.is_tmp_autofree
&& !g.inside_const && !g.is_builtin_mod && !g.inside_const && !g.is_builtin_mod
// g.write('/* af=$arg.is_tmp_autofree */') // g.write('/* af=$arg.is_tmp_autofree */')
// some c fn definitions dont have args (cfns.v) or are not updated in checker // some c fn definitions dont have args (cfns.v) or are not updated in checker
@ -1053,7 +1052,7 @@ fn (mut g Gen) call_args(node ast.CallExpr) {
varg_type := expected_types.last() varg_type := expected_types.last()
variadic_count := args.len - arg_nr variadic_count := args.len - arg_nr
arr_sym := g.table.get_type_symbol(varg_type) arr_sym := g.table.get_type_symbol(varg_type)
mut arr_info := arr_sym.info as table.Array mut arr_info := arr_sym.info as ast.Array
if varg_type.has_flag(.generic) { if varg_type.has_flag(.generic) {
if fn_def := g.table.find_fn(node.name) { if fn_def := g.table.find_fn(node.name) {
varg_type_name := g.table.type_to_str(varg_type) varg_type_name := g.table.type_to_str(varg_type)
@ -1088,9 +1087,9 @@ fn (mut g Gen) call_args(node ast.CallExpr) {
} }
[inline] [inline]
fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type, lang table.Language) { fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type ast.Type, lang ast.Language) {
arg_is_ptr := expected_type.is_ptr() || expected_type.idx() in table.pointer_type_idxs arg_is_ptr := expected_type.is_ptr() || expected_type.idx() in ast.pointer_type_idxs
expr_is_ptr := arg.typ.is_ptr() || arg.typ.idx() in table.pointer_type_idxs expr_is_ptr := arg.typ.is_ptr() || arg.typ.idx() in ast.pointer_type_idxs
if expected_type == 0 { if expected_type == 0 {
g.checker_bug('ref_or_deref_arg expected_type is 0', arg.pos) g.checker_bug('ref_or_deref_arg expected_type is 0', arg.pos)
} }
@ -1158,7 +1157,7 @@ fn (g &Gen) fileis(s string) bool {
return g.file.path.contains(s) return g.file.path.contains(s)
} }
fn (mut g Gen) write_fn_attrs(attrs []table.Attr) string { fn (mut g Gen) write_fn_attrs(attrs []ast.Attr) string {
mut msvc_attrs := '' mut msvc_attrs := ''
for attr in attrs { for attr in attrs {
match attr.name { match attr.name {

View File

@ -4,7 +4,6 @@
module c module c
import v.ast import v.ast
import v.table
import v.util import v.util
fn (mut g Gen) index_expr(node ast.IndexExpr) { fn (mut g Gen) index_expr(node ast.IndexExpr) {
@ -46,7 +45,7 @@ fn (mut g Gen) range_expr(node ast.IndexExpr, range ast.RangeExpr) {
g.expr(node.left) g.expr(node.left)
} else if sym.kind == .array_fixed { } else if sym.kind == .array_fixed {
// Convert a fixed array to V array when doing `fixed_arr[start..end]` // Convert a fixed array to V array when doing `fixed_arr[start..end]`
info := sym.info as table.ArrayFixed info := sym.info as ast.ArrayFixed
g.write('array_slice(new_array_from_c_array(') g.write('array_slice(new_array_from_c_array(')
g.write('$info.size') g.write('$info.size')
g.write(', $info.size') g.write(', $info.size')
@ -77,7 +76,7 @@ fn (mut g Gen) range_expr(node ast.IndexExpr, range ast.RangeExpr) {
if range.has_high { if range.has_high {
g.expr(range.high) g.expr(range.high)
} else if sym.kind == .array_fixed { } else if sym.kind == .array_fixed {
info := sym.info as table.ArrayFixed info := sym.info as ast.ArrayFixed
g.write('$info.size') g.write('$info.size')
} else if node.left_type.is_ptr() { } else if node.left_type.is_ptr() {
g.write('(') g.write('(')
@ -92,10 +91,10 @@ fn (mut g Gen) range_expr(node ast.IndexExpr, range ast.RangeExpr) {
g.write(')') g.write(')')
} }
fn (mut g Gen) index_of_array(node ast.IndexExpr, sym table.TypeSymbol) { fn (mut g Gen) index_of_array(node ast.IndexExpr, sym ast.TypeSymbol) {
gen_or := node.or_expr.kind != .absent || node.is_option gen_or := node.or_expr.kind != .absent || node.is_option
left_is_ptr := node.left_type.is_ptr() left_is_ptr := node.left_type.is_ptr()
info := sym.info as table.Array info := sym.info as ast.Array
elem_type_str := g.typ(info.elem_type) elem_type_str := g.typ(info.elem_type)
elem_type := info.elem_type elem_type := info.elem_type
elem_typ := g.table.get_type_symbol(elem_type) elem_typ := g.table.get_type_symbol(elem_type)
@ -104,7 +103,7 @@ fn (mut g Gen) index_of_array(node ast.IndexExpr, sym table.TypeSymbol) {
is_selector := node.left is ast.SelectorExpr is_selector := node.left is ast.SelectorExpr
if g.is_assign_lhs && !is_selector && node.is_setter { if g.is_assign_lhs && !is_selector && node.is_setter {
is_direct_array_access := g.fn_decl != 0 && g.fn_decl.is_direct_arr is_direct_array_access := g.fn_decl != 0 && g.fn_decl.is_direct_arr
is_op_assign := g.assign_op != .assign && info.elem_type != table.string_type is_op_assign := g.assign_op != .assign && info.elem_type != ast.string_type
array_ptr_type_str := match elem_typ.kind { array_ptr_type_str := match elem_typ.kind {
.function { 'voidptr*' } .function { 'voidptr*' }
else { '$elem_type_str*' } else { '$elem_type_str*' }
@ -175,7 +174,7 @@ fn (mut g Gen) index_of_array(node ast.IndexExpr, sym table.TypeSymbol) {
.function { 'voidptr*' } .function { 'voidptr*' }
else { '$elem_type_str*' } else { '$elem_type_str*' }
} }
needs_clone := info.elem_type == table.string_type_idx && g.is_autofree && !g.is_assign_lhs needs_clone := info.elem_type == ast.string_type_idx && g.is_autofree && !g.is_assign_lhs
is_gen_or_and_assign_rhs := gen_or && !g.discard_or_result is_gen_or_and_assign_rhs := gen_or && !g.discard_or_result
cur_line := if is_gen_or_and_assign_rhs { cur_line := if is_gen_or_and_assign_rhs {
line := g.go_before_stmt(0) line := g.go_before_stmt(0)
@ -193,7 +192,7 @@ fn (mut g Gen) index_of_array(node ast.IndexExpr, sym table.TypeSymbol) {
g.write('/*2*/string_clone(') g.write('/*2*/string_clone(')
} }
if g.is_fn_index_call { if g.is_fn_index_call {
if elem_typ.info is table.FnType { if elem_typ.info is ast.FnType {
g.write('((') g.write('((')
g.write_fn_ptr_decl(&elem_typ.info, '') g.write_fn_ptr_decl(&elem_typ.info, '')
g.write(')(*($array_ptr_type_str)/*ee elem_typ */array_get(') g.write(')(*($array_ptr_type_str)/*ee elem_typ */array_get(')
@ -257,11 +256,11 @@ fn (mut g Gen) index_of_array(node ast.IndexExpr, sym table.TypeSymbol) {
} }
} }
fn (mut g Gen) index_of_fixed_array(node ast.IndexExpr, sym table.TypeSymbol) { fn (mut g Gen) index_of_fixed_array(node ast.IndexExpr, sym ast.TypeSymbol) {
info := sym.info as table.ArrayFixed info := sym.info as ast.ArrayFixed
elem_type := info.elem_type elem_type := info.elem_type
elem_sym := g.table.get_type_symbol(elem_type) elem_sym := g.table.get_type_symbol(elem_type)
is_fn_index_call := g.is_fn_index_call && elem_sym.info is table.FnType is_fn_index_call := g.is_fn_index_call && elem_sym.info is ast.FnType
if is_fn_index_call { if is_fn_index_call {
g.write('(*') g.write('(*')
@ -289,17 +288,17 @@ fn (mut g Gen) index_of_fixed_array(node ast.IndexExpr, sym table.TypeSymbol) {
} }
} }
fn (mut g Gen) index_of_map(node ast.IndexExpr, sym table.TypeSymbol) { fn (mut g Gen) index_of_map(node ast.IndexExpr, sym ast.TypeSymbol) {
gen_or := node.or_expr.kind != .absent || node.is_option gen_or := node.or_expr.kind != .absent || node.is_option
left_is_ptr := node.left_type.is_ptr() left_is_ptr := node.left_type.is_ptr()
info := sym.info as table.Map info := sym.info as ast.Map
key_type_str := g.typ(info.key_type) key_type_str := g.typ(info.key_type)
elem_type := info.value_type elem_type := info.value_type
elem_type_str := g.typ(elem_type) elem_type_str := g.typ(elem_type)
elem_typ := g.table.get_type_symbol(elem_type) elem_typ := g.table.get_type_symbol(elem_type)
get_and_set_types := elem_typ.kind in [.struct_, .map] get_and_set_types := elem_typ.kind in [.struct_, .map]
if g.is_assign_lhs && !g.is_arraymap_set && !get_and_set_types { if g.is_assign_lhs && !g.is_arraymap_set && !get_and_set_types {
if g.assign_op == .assign || info.value_type == table.string_type { if g.assign_op == .assign || info.value_type == ast.string_type {
g.is_arraymap_set = true g.is_arraymap_set = true
g.write('map_set_1(') g.write('map_set_1(')
} else { } else {
@ -335,7 +334,7 @@ fn (mut g Gen) index_of_map(node ast.IndexExpr, sym table.TypeSymbol) {
g.arraymap_set_pos = g.out.len g.arraymap_set_pos = g.out.len
g.write(', &($elem_type_str[]) { ') g.write(', &($elem_type_str[]) { ')
} }
if g.assign_op != .assign && info.value_type != table.string_type { if g.assign_op != .assign && info.value_type != ast.string_type {
zero := g.type_default(info.value_type) zero := g.type_default(info.value_type)
g.write('$zero })))') g.write('$zero })))')
} }
@ -370,7 +369,7 @@ fn (mut g Gen) index_of_map(node ast.IndexExpr, sym table.TypeSymbol) {
g.write('$elem_type_str* $tmp_opt_ptr = ($elem_type_str*)/*ee elem_ptr_typ */(map_get_1_check(') g.write('$elem_type_str* $tmp_opt_ptr = ($elem_type_str*)/*ee elem_ptr_typ */(map_get_1_check(')
} else { } else {
if g.is_fn_index_call { if g.is_fn_index_call {
if elem_typ.info is table.FnType { if elem_typ.info is ast.FnType {
g.write('((') g.write('((')
g.write_fn_ptr_decl(&elem_typ.info, '') g.write_fn_ptr_decl(&elem_typ.info, '')
g.write(')(*(voidptr*)map_get_1(') g.write(')(*(voidptr*)map_get_1(')

View File

@ -3,7 +3,7 @@
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module c module c
import v.table import v.ast
import v.util import v.util
import strings import strings
@ -18,7 +18,7 @@ import strings
// return res; // return res;
// } // }
// Codegen json_decode/encode funcs // Codegen json_decode/encode funcs
fn (mut g Gen) gen_json_for_type(typ table.Type) { fn (mut g Gen) gen_json_for_type(typ ast.Type) {
utyp := g.unwrap_generic(typ) utyp := g.unwrap_generic(typ)
mut dec := strings.new_builder(100) mut dec := strings.new_builder(100)
mut enc := strings.new_builder(100) mut enc := strings.new_builder(100)
@ -73,13 +73,13 @@ $enc_fn_dec {
// enc += g.encode_array(t) // enc += g.encode_array(t)
} else if sym.kind == .map { } else if sym.kind == .map {
// Handle maps // Handle maps
m := sym.info as table.Map m := sym.info as ast.Map
g.gen_json_for_type(m.key_type) g.gen_json_for_type(m.key_type)
g.gen_json_for_type(m.value_type) g.gen_json_for_type(m.value_type)
dec.writeln(g.decode_map(m.key_type, m.value_type)) dec.writeln(g.decode_map(m.key_type, m.value_type))
enc.writeln(g.encode_map(m.key_type, m.value_type)) enc.writeln(g.encode_map(m.key_type, m.value_type))
} else if sym.kind == .alias { } else if sym.kind == .alias {
a := sym.info as table.Alias a := sym.info as ast.Alias
parent_typ := a.parent_type parent_typ := a.parent_type
psym := g.table.get_type_symbol(parent_typ) psym := g.table.get_type_symbol(parent_typ)
if is_js_prim(g.typ(parent_typ)) { if is_js_prim(g.typ(parent_typ)) {
@ -87,14 +87,14 @@ $enc_fn_dec {
return return
} }
enc.writeln('\to = cJSON_CreateObject();') enc.writeln('\to = cJSON_CreateObject();')
if psym.info !is table.Struct { if psym.info !is ast.Struct {
verror('json: $sym.name is not struct') verror('json: $sym.name is not struct')
} }
g.gen_struct_enc_dec(psym.info, styp, mut enc, mut dec) g.gen_struct_enc_dec(psym.info, styp, mut enc, mut dec)
} else { } else {
enc.writeln('\to = cJSON_CreateObject();') enc.writeln('\to = cJSON_CreateObject();')
// Structs. Range through fields // Structs. Range through fields
if sym.info !is table.Struct { if sym.info !is ast.Struct {
verror('json: $sym.name is not struct') verror('json: $sym.name is not struct')
} }
g.gen_struct_enc_dec(sym.info, styp, mut enc, mut dec) g.gen_struct_enc_dec(sym.info, styp, mut enc, mut dec)
@ -110,8 +110,8 @@ $enc_fn_dec {
} }
[inline] [inline]
fn (mut g Gen) gen_struct_enc_dec(type_info table.TypeInfo, styp string, mut enc strings.Builder, mut dec strings.Builder) { fn (mut g Gen) gen_struct_enc_dec(type_info ast.TypeInfo, styp string, mut enc strings.Builder, mut dec strings.Builder) {
info := type_info as table.Struct info := type_info as ast.Struct
for field in info.fields { for field in info.fields {
if field.attrs.contains('skip') { if field.attrs.contains('skip') {
continue continue
@ -143,7 +143,7 @@ fn (mut g Gen) gen_struct_enc_dec(type_info table.TypeInfo, styp string, mut enc
// it has to be decoded from a unix timestamp number // it has to be decoded from a unix timestamp number
dec.writeln('\tres.${c_name(field.name)} = time__unix(json__decode_u64(js_get(root, "$name")));') dec.writeln('\tres.${c_name(field.name)} = time__unix(json__decode_u64(js_get(root, "$name")));')
} else if field_sym.kind == .alias { } else if field_sym.kind == .alias {
alias := field_sym.info as table.Alias alias := field_sym.info as ast.Alias
parent_type := g.typ(alias.parent_type) parent_type := g.typ(alias.parent_type)
parent_dec_name := js_dec_name(parent_type) parent_dec_name := js_dec_name(parent_type)
if is_js_prim(parent_type) { if is_js_prim(parent_type) {
@ -171,7 +171,7 @@ fn (mut g Gen) gen_struct_enc_dec(type_info table.TypeInfo, styp string, mut enc
mut enc_name := js_enc_name(field_type) mut enc_name := js_enc_name(field_type)
if !is_js_prim(field_type) { if !is_js_prim(field_type) {
if field_sym.kind == .alias { if field_sym.kind == .alias {
ainfo := field_sym.info as table.Alias ainfo := field_sym.info as ast.Alias
enc_name = js_enc_name(g.typ(ainfo.parent_type)) enc_name = js_enc_name(g.typ(ainfo.parent_type))
} }
} }
@ -206,7 +206,7 @@ fn is_js_prim(typ string) bool {
] ]
} }
fn (mut g Gen) decode_array(value_type table.Type) string { fn (mut g Gen) decode_array(value_type ast.Type) string {
styp := g.typ(value_type) styp := g.typ(value_type)
fn_name := js_dec_name(styp) fn_name := js_dec_name(styp)
mut s := '' mut s := ''
@ -236,7 +236,7 @@ fn (mut g Gen) decode_array(value_type table.Type) string {
' '
} }
fn (mut g Gen) encode_array(value_type table.Type) string { fn (mut g Gen) encode_array(value_type ast.Type) string {
styp := g.typ(value_type) styp := g.typ(value_type)
fn_name := js_enc_name(styp) fn_name := js_enc_name(styp)
return ' return '
@ -247,7 +247,7 @@ fn (mut g Gen) encode_array(value_type table.Type) string {
' '
} }
fn (mut g Gen) decode_map(key_type table.Type, value_type table.Type) string { fn (mut g Gen) decode_map(key_type ast.Type, value_type ast.Type) string {
styp := g.typ(key_type) styp := g.typ(key_type)
styp_v := g.typ(value_type) styp_v := g.typ(value_type)
key_type_symbol := g.table.get_type_symbol(key_type) key_type_symbol := g.table.get_type_symbol(key_type)
@ -281,7 +281,7 @@ fn (mut g Gen) decode_map(key_type table.Type, value_type table.Type) string {
' '
} }
fn (mut g Gen) encode_map(key_type table.Type, value_type table.Type) string { fn (mut g Gen) encode_map(key_type ast.Type, value_type ast.Type) string {
styp := g.typ(key_type) styp := g.typ(key_type)
styp_v := g.typ(value_type) styp_v := g.typ(value_type)
fn_name_v := js_enc_name(styp_v) fn_name_v := js_enc_name(styp_v)

View File

@ -4,7 +4,6 @@ module c
import v.ast import v.ast
import strings import strings
import v.table
import v.util import v.util
// pg,mysql etc // pg,mysql etc
@ -133,7 +132,7 @@ fn (mut g Gen) sqlite3_stmt(node ast.SqlStmt, typ SqlType) {
continue continue
} }
x := '${node.object_var_name}.$field.name' x := '${node.object_var_name}.$field.name'
if field.typ == table.string_type { if field.typ == ast.string_type {
g.writeln('sqlite3_bind_text($g.sql_stmt_name, ${i + 0}, ${x}.str, ${x}.len, 0);') g.writeln('sqlite3_bind_text($g.sql_stmt_name, ${i + 0}, ${x}.str, ${x}.len, 0);')
} else if g.table.type_symbols[int(field.typ)].kind == .struct_ { } else if g.table.type_symbols[int(field.typ)].kind == .struct_ {
// insert again // insert again
@ -249,14 +248,14 @@ fn (mut g Gen) sqlite3_select_expr(node ast.SqlExpr, sub bool, line string, sql_
// array_User array_tmp; // array_User array_tmp;
// for { User tmp; ... array_tmp << tmp; } // for { User tmp; ... array_tmp << tmp; }
array_sym := g.table.get_type_symbol(node.typ) array_sym := g.table.get_type_symbol(node.typ)
array_info := array_sym.info as table.Array array_info := array_sym.info as ast.Array
elem_type_str = g.typ(array_info.elem_type) elem_type_str = g.typ(array_info.elem_type)
g.writeln('$styp ${tmp}_array = __new_array(0, 10, sizeof($elem_type_str));') g.writeln('$styp ${tmp}_array = __new_array(0, 10, sizeof($elem_type_str));')
g.writeln('while (1) {') g.writeln('while (1) {')
g.writeln('\t$elem_type_str $tmp = ($elem_type_str) {') g.writeln('\t$elem_type_str $tmp = ($elem_type_str) {')
// //
sym := g.table.get_type_symbol(array_info.elem_type) sym := g.table.get_type_symbol(array_info.elem_type)
info := sym.info as table.Struct info := sym.info as ast.Struct
for i, field in info.fields { for i, field in info.fields {
g.zero_struct_field(field) g.zero_struct_field(field)
if i != info.fields.len - 1 { if i != info.fields.len - 1 {
@ -271,7 +270,7 @@ fn (mut g Gen) sqlite3_select_expr(node ast.SqlExpr, sub bool, line string, sql_
// If we don't, string values are going to be nil etc for fields that are not returned // If we don't, string values are going to be nil etc for fields that are not returned
// by the db engine. // by the db engine.
sym := g.table.get_type_symbol(node.typ) sym := g.table.get_type_symbol(node.typ)
info := sym.info as table.Struct info := sym.info as ast.Struct
for i, field in info.fields { for i, field in info.fields {
g.zero_struct_field(field) g.zero_struct_field(field)
if i != info.fields.len - 1 { if i != info.fields.len - 1 {
@ -293,7 +292,7 @@ fn (mut g Gen) sqlite3_select_expr(node ast.SqlExpr, sub bool, line string, sql_
} }
for i, field in node.fields { for i, field in node.fields {
mut func := 'sqlite3_column_int' mut func := 'sqlite3_column_int'
if field.typ == table.string_type { if field.typ == ast.string_type {
func = 'sqlite3_column_text' func = 'sqlite3_column_text'
string_data := g.new_tmp_var() string_data := g.new_tmp_var()
g.writeln('byteptr $string_data = ${func}($g.sql_stmt_name, $i);') g.writeln('byteptr $string_data = ${func}($g.sql_stmt_name, $i);')
@ -415,9 +414,9 @@ fn (mut g Gen) expr_to_sql(expr ast.Expr, typ SqlType) {
g.inc_sql_i() g.inc_sql_i()
info := expr.info as ast.IdentVar info := expr.info as ast.IdentVar
ityp := info.typ ityp := info.typ
if ityp == table.string_type { if ityp == ast.string_type {
g.sql_bind_string('${expr.name}.str', '${expr.name}.len', typ) g.sql_bind_string('${expr.name}.str', '${expr.name}.len', typ)
} else if ityp == table.int_type { } else if ityp == ast.int_type {
g.sql_bind_int(expr.name, typ) g.sql_bind_int(expr.name, typ)
} else { } else {
verror('bad sql type=$ityp ident_name=$expr.name') verror('bad sql type=$ityp ident_name=$expr.name')
@ -426,7 +425,7 @@ fn (mut g Gen) expr_to_sql(expr ast.Expr, typ SqlType) {
} }
ast.SelectorExpr { ast.SelectorExpr {
g.inc_sql_i() g.inc_sql_i()
if expr.typ == table.int_type { if expr.typ == ast.int_type {
if expr.expr !is ast.Ident { if expr.expr !is ast.Ident {
verror('orm selector not ident') verror('orm selector not ident')
} }

View File

@ -4,7 +4,6 @@ module c
import v.ast import v.ast
import v.util import v.util
import v.table
fn (mut g Gen) write_str_fn_definitions() { fn (mut g Gen) write_str_fn_definitions() {
// _STR function can't be defined in vlib // _STR function can't be defined in vlib
@ -26,7 +25,7 @@ void _STR_PRINT_ARG(const char *fmt, char** refbufp, int *nbytes, int *memsize,
} }
// increase buffer (somewhat exponentially) // increase buffer (somewhat exponentially)
*memsize += (*memsize + *memsize) / 3 + guess; *memsize += (*memsize + *memsize) / 3 + guess;
#ifdef _VGCBOEHM #ifdef _VGCBOEHM
*refbufp = (char*)GC_REALLOC((void*)*refbufp, *memsize); *refbufp = (char*)GC_REALLOC((void*)*refbufp, *memsize);
#else #else
*refbufp = (char*)realloc((void*)*refbufp, *memsize); *refbufp = (char*)realloc((void*)*refbufp, *memsize);
@ -39,7 +38,7 @@ string _STR(const char *fmt, int nfmts, ...) {
va_list argptr; va_list argptr;
int memsize = 128; int memsize = 128;
int nbytes = 0; int nbytes = 0;
#ifdef _VGCBOEHM #ifdef _VGCBOEHM
char* buf = (char*)GC_MALLOC(memsize); char* buf = (char*)GC_MALLOC(memsize);
#else #else
char* buf = (char*)malloc(memsize); char* buf = (char*)malloc(memsize);
@ -222,7 +221,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
mut typ := g.unwrap_generic(node.expr_types[i]) mut typ := g.unwrap_generic(node.expr_types[i])
sym := g.table.get_type_symbol(typ) sym := g.table.get_type_symbol(typ)
if sym.kind == .alias { if sym.kind == .alias {
typ = (sym.info as table.Alias).parent_type typ = (sym.info as ast.Alias).parent_type
} }
// write correct format specifier to intermediate string // write correct format specifier to intermediate string
g.write('%') g.write('%')
@ -256,11 +255,11 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
g.write('${fmt}c') g.write('${fmt}c')
} else { } else {
g.write('$fmt"PRI${fspec:c}') g.write('$fmt"PRI${fspec:c}')
if typ in [table.i8_type, table.byte_type] { if typ in [ast.i8_type, ast.byte_type] {
g.write('8') g.write('8')
} else if typ in [table.i16_type, table.u16_type] { } else if typ in [ast.i16_type, ast.u16_type] {
g.write('16') g.write('16')
} else if typ in [table.i64_type, table.u64_type] { } else if typ in [ast.i64_type, ast.u64_type] {
g.write('64') g.write('64')
} else { } else {
g.write('32') g.write('32')
@ -280,7 +279,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
// Build args // Build args
for i, expr in node.exprs { for i, expr in node.exprs {
typ := g.unwrap_generic(node.expr_types[i]) typ := g.unwrap_generic(node.expr_types[i])
if typ == table.string_type { if typ == ast.string_type {
if g.inside_vweb_tmpl { if g.inside_vweb_tmpl {
g.write('vweb__filter(') g.write('vweb__filter(')
if expr.is_auto_deref_var() { if expr.is_auto_deref_var() {
@ -299,11 +298,11 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
} else if typ.is_number() || typ.is_pointer() || node.fmts[i] == `d` { } else if typ.is_number() || typ.is_pointer() || node.fmts[i] == `d` {
if typ.is_signed() && node.fmts[i] in [`x`, `X`, `o`] { if typ.is_signed() && node.fmts[i] in [`x`, `X`, `o`] {
// convert to unsigned first befors C's integer propagation strikes // convert to unsigned first befors C's integer propagation strikes
if typ == table.i8_type { if typ == ast.i8_type {
g.write('(byte)(') g.write('(byte)(')
} else if typ == table.i16_type { } else if typ == ast.i16_type {
g.write('(u16)(') g.write('(u16)(')
} else if typ == table.int_type { } else if typ == ast.int_type {
g.write('(u32)(') g.write('(u32)(')
} else { } else {
g.write('(u64)(') g.write('(u64)(')
@ -335,7 +334,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) {
g.write(')') g.write(')')
} }
fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) { fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type) {
is_shared := etype.has_flag(.shared_f) is_shared := etype.has_flag(.shared_f)
mut typ := etype mut typ := etype
if is_shared { if is_shared {
@ -343,7 +342,7 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) {
} }
mut sym := g.table.get_type_symbol(typ) mut sym := g.table.get_type_symbol(typ)
// when type is alias, print the aliased value // when type is alias, print the aliased value
if mut sym.info is table.Alias { if mut sym.info is ast.Alias {
parent_sym := g.table.get_type_symbol(sym.info.parent_type) parent_sym := g.table.get_type_symbol(sym.info.parent_type)
if parent_sym.has_method('str') { if parent_sym.has_method('str') {
typ = sym.info.parent_type typ = sym.info.parent_type
@ -356,9 +355,9 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype table.Type) {
g.write('${str_fn_name}(') g.write('${str_fn_name}(')
g.expr(expr) g.expr(expr)
g.write(')') g.write(')')
} else if typ == table.string_type { } else if typ == ast.string_type {
g.expr(expr) g.expr(expr)
} else if typ == table.bool_type { } else if typ == ast.bool_type {
g.expr(expr) g.expr(expr)
g.write(' ? _SLIT("true") : _SLIT("false")') g.write(' ? _SLIT("true") : _SLIT("false")')
} else if sym.kind == .none_ { } else if sym.kind == .none_ {

View File

@ -1,5 +1,6 @@
module js module js
import v.table
import v.ast
fn (mut g JsGen) to_js_typ_def_val(s string) string { fn (mut g JsGen) to_js_typ_def_val(s string) string {
mut dval := '' mut dval := ''
@ -13,25 +14,26 @@ fn (mut g JsGen) to_js_typ_def_val(s string) string {
return dval return dval
} }
fn (mut g JsGen) to_js_typ_val(t table.Type) string { fn (mut g JsGen) to_js_typ_val(t ast.Type) string {
sym := g.table.get_type_symbol(t) sym := g.table.get_type_symbol(t)
mut styp := '' mut styp := ''
mut prefix := if g.file.mod.name == 'builtin' { 'new ' } else { '' } mut prefix := if g.file.mod.name == 'builtin' { 'new ' } else { '' }
match sym.kind { match sym.kind {
.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64, .f32, .f64, .int_literal, .float_literal, .size_t { .i8, .i16, .int, .i64, .byte, .u16, .u32, .u64, .f32, .f64, .int_literal, .float_literal,
styp = '${prefix}${g.sym_to_js_typ(sym)}(0)' .size_t {
styp = '$prefix${g.sym_to_js_typ(sym)}(0)'
} }
.bool { .bool {
styp = '${prefix}${g.sym_to_js_typ(sym)}(false)' styp = '$prefix${g.sym_to_js_typ(sym)}(false)'
} }
.string { .string {
styp = '${prefix}${g.sym_to_js_typ(sym)}("")' styp = '$prefix${g.sym_to_js_typ(sym)}("")'
} }
.map { .map {
styp = 'new Map()' styp = 'new Map()'
} }
.array { .array {
styp = '${prefix}${g.sym_to_js_typ(sym)}()' styp = '$prefix${g.sym_to_js_typ(sym)}()'
} }
.struct_ { .struct_ {
styp = 'new ${g.js_name(sym.name)}(${g.to_js_typ_def_val(sym.name)})' styp = 'new ${g.js_name(sym.name)}(${g.to_js_typ_def_val(sym.name)})'
@ -44,26 +46,60 @@ fn (mut g JsGen) to_js_typ_val(t table.Type) string {
return styp return styp
} }
fn (mut g JsGen) sym_to_js_typ(sym table.TypeSymbol) string { fn (mut g JsGen) sym_to_js_typ(sym ast.TypeSymbol) string {
mut styp := '' mut styp := ''
match sym.kind { match sym.kind {
.i8 { styp = 'i8' } .i8 {
.i16 { styp = 'i16' } styp = 'i8'
.int { styp = 'int' } }
.i64 { styp = 'i64' } .i16 {
.byte { styp = 'byte' } styp = 'i16'
.u16 { styp = 'u16' } }
.u32 { styp = 'u32' } .int {
.u64 { styp = 'u64' } styp = 'int'
.f32 { styp = 'f32' } }
.f64 { styp = 'f64' } .i64 {
.int_literal { styp = 'int_literal' } styp = 'i64'
.float_literal { styp = 'float_literal' } }
.size_t { styp = 'size_t' } .byte {
.bool { styp = 'bool' } styp = 'byte'
.string { styp = 'string' } }
.map { styp = 'map' } .u16 {
.array { styp = 'array' } styp = 'u16'
}
.u32 {
styp = 'u32'
}
.u64 {
styp = 'u64'
}
.f32 {
styp = 'f32'
}
.f64 {
styp = 'f64'
}
.int_literal {
styp = 'int_literal'
}
.float_literal {
styp = 'float_literal'
}
.size_t {
styp = 'size_t'
}
.bool {
styp = 'bool'
}
.string {
styp = 'string'
}
.map {
styp = 'map'
}
.array {
styp = 'array'
}
else { else {
// TODO // TODO
styp = 'undefined' styp = 'undefined'
@ -73,7 +109,7 @@ fn (mut g JsGen) sym_to_js_typ(sym table.TypeSymbol) string {
} }
// V type to JS type // V type to JS type
pub fn (mut g JsGen) typ(t table.Type) string { pub fn (mut g JsGen) typ(t ast.Type) string {
sym := g.table.get_type_symbol(t) sym := g.table.get_type_symbol(t)
mut styp := '' mut styp := ''
match sym.kind { match sym.kind {
@ -90,7 +126,8 @@ pub fn (mut g JsGen) typ(t table.Type) string {
.byteptr, .charptr { .byteptr, .charptr {
styp = '${g.sym_to_js_typ(sym)}' styp = '${g.sym_to_js_typ(sym)}'
} }
.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64, .f32, .f64, .int_literal, .float_literal, .size_t { .i8, .i16, .int, .i64, .byte, .u16, .u32, .u64, .f32, .f64, .int_literal, .float_literal,
.size_t {
styp = '${g.sym_to_js_typ(sym)}' styp = '${g.sym_to_js_typ(sym)}'
} }
.bool { .bool {
@ -104,11 +141,11 @@ pub fn (mut g JsGen) typ(t table.Type) string {
} }
// 'array_array_int' => 'number[][]' // 'array_array_int' => 'number[][]'
.array { .array {
info := sym.info as table.Array info := sym.info as ast.Array
styp = '${g.sym_to_js_typ(sym)}(${g.typ(info.elem_type)})' styp = '${g.sym_to_js_typ(sym)}(${g.typ(info.elem_type)})'
} }
.array_fixed { .array_fixed {
info := sym.info as table.ArrayFixed info := sym.info as ast.ArrayFixed
styp = '${g.sym_to_js_typ(sym)}(${g.typ(info.elem_type)})' styp = '${g.sym_to_js_typ(sym)}(${g.typ(info.elem_type)})'
} }
.chan { .chan {
@ -116,7 +153,7 @@ pub fn (mut g JsGen) typ(t table.Type) string {
} }
// 'map[string]int' => 'Map<string, number>' // 'map[string]int' => 'Map<string, number>'
.map { .map {
info := sym.info as table.Map info := sym.info as ast.Map
key := g.typ(info.key_type) key := g.typ(info.key_type)
val := g.typ(info.value_type) val := g.typ(info.value_type)
styp = 'Map<$key, $val>' styp = 'Map<$key, $val>'
@ -131,7 +168,7 @@ pub fn (mut g JsGen) typ(t table.Type) string {
.generic_struct_inst {} .generic_struct_inst {}
// 'multi_return_int_int' => '[number, number]' // 'multi_return_int_int' => '[number, number]'
.multi_return { .multi_return {
info := sym.info as table.MultiReturn info := sym.info as ast.MultiReturn
types := info.types.map(g.typ(it)) types := info.types.map(g.typ(it))
joined := types.join(', ') joined := types.join(', ')
styp = '[$joined]' styp = '[$joined]'
@ -153,7 +190,7 @@ pub fn (mut g JsGen) typ(t table.Type) string {
} }
// 'anon_fn_7_7_1' => '(a number, b number) => void' // 'anon_fn_7_7_1' => '(a number, b number) => void'
.function { .function {
info := sym.info as table.FnType info := sym.info as ast.FnType
styp = g.fn_typ(info.func.params, info.func.return_type) styp = g.fn_typ(info.func.params, info.func.return_type)
} }
.interface_ { .interface_ {
@ -181,7 +218,7 @@ pub fn (mut g JsGen) typ(t table.Type) string {
return styp return styp
} }
fn (mut g JsGen) fn_typ(args []table.Param, return_type table.Type) string { fn (mut g JsGen) fn_typ(args []ast.Param, return_type ast.Type) string {
mut res := '(' mut res := '('
for i, arg in args { for i, arg in args {
res += '$arg.name: ${g.typ(arg.typ)}' res += '$arg.name: ${g.typ(arg.typ)}'
@ -194,7 +231,9 @@ fn (mut g JsGen) fn_typ(args []table.Param, return_type table.Type) string {
fn (mut g JsGen) struct_typ(s string) string { fn (mut g JsGen) struct_typ(s string) string {
ns := get_ns(s) ns := get_ns(s)
if ns == 'JS' { return s[3..] } if ns == 'JS' {
return s[3..]
}
mut name := if ns == g.ns.name { s.split('.').last() } else { g.get_alias(s) } mut name := if ns == g.ns.name { s.split('.').last() } else { g.get_alias(s) }
mut styp := '' mut styp := ''
for i, v in name.split('.') { for i, v in name.split('.') {
@ -210,26 +249,25 @@ fn (mut g JsGen) struct_typ(s string) string {
return styp + '["prototype"]' return styp + '["prototype"]'
} }
struct BuiltinPrototypeCongig { struct BuiltinPrototypeConfig {
typ_name string typ_name string
val_name string = 'val' val_name string = 'val'
default_value string default_value string
constructor string = 'this.val = val' constructor string = 'this.val = val'
value_of string = 'this.val' value_of string = 'this.val'
to_string string = 'this.val.toString()' to_string string = 'this.val.toString()'
eq string = 'this.val === other.val' eq string = 'this.val === other.val'
extras string extras string
has_strfn bool has_strfn bool
} }
// ugly arguments but not sure a config struct would be worth it fn (mut g JsGen) gen_builtin_prototype(c BuiltinPrototypeConfig) {
fn (mut g JsGen) gen_builtin_prototype(c BuiltinPrototypeCongig) { g.writeln('function ${c.typ_name}($c.val_name = $c.default_value) { $c.constructor }')
g.writeln('function ${c.typ_name}(${c.val_name} = ${c.default_value}) { ${c.constructor} }')
g.writeln('${c.typ_name}.prototype = {') g.writeln('${c.typ_name}.prototype = {')
g.inc_indent() g.inc_indent()
g.writeln('${c.val_name}: ${c.default_value},') g.writeln('$c.val_name: $c.default_value,')
if c.extras.len > 0 { if c.extras.len > 0 {
g.writeln('${c.extras},') g.writeln('$c.extras,')
} }
for method in g.method_fn_decls[c.typ_name] { for method in g.method_fn_decls[c.typ_name] {
g.inside_def_typ_decl = true g.inside_def_typ_decl = true
@ -237,10 +275,12 @@ fn (mut g JsGen) gen_builtin_prototype(c BuiltinPrototypeCongig) {
g.inside_def_typ_decl = false g.inside_def_typ_decl = false
g.writeln(',') g.writeln(',')
} }
g.writeln('valueOf() { return ${c.value_of} },') g.writeln('valueOf() { return $c.value_of },')
g.writeln('toString() { return ${c.to_string} },') g.writeln('toString() { return $c.to_string },')
g.writeln('eq(other) { return ${c.eq} },') g.writeln('eq(other) { return $c.eq },')
if c.has_strfn { g.writeln('str() { return new string(this.toString()) }') } if c.has_strfn {
g.writeln('str() { return new string(this.toString()) }')
}
g.dec_indent() g.dec_indent()
g.writeln('};\n') g.writeln('};\n')
} }
@ -253,39 +293,39 @@ fn (mut g JsGen) gen_builtin_type_defs() {
match typ_name { match typ_name {
'i8', 'i16', 'int', 'i64', 'u16', 'u32', 'u64', 'int_literal', 'size_t' { 'i8', 'i16', 'int', 'i64', 'u16', 'u32', 'u64', 'int_literal', 'size_t' {
// TODO: Bounds checking // TODO: Bounds checking
g.gen_builtin_prototype({ g.gen_builtin_prototype(
typ_name: typ_name typ_name: typ_name
default_value: 'new Number(0)' default_value: 'new Number(0)'
constructor: 'this.val = val | 0' constructor: 'this.val = val | 0'
value_of: 'this.val | 0' value_of: 'this.val | 0'
to_string: 'this.valueOf().toString()' to_string: 'this.valueOf().toString()'
eq: 'this.valueOf() === other.valueOf()' eq: 'this.valueOf() === other.valueOf()'
}) )
} }
'byte' { 'byte' {
g.gen_builtin_prototype({ g.gen_builtin_prototype(
typ_name: typ_name typ_name: typ_name
default_value: 'new Number(0)' default_value: 'new Number(0)'
constructor: 'this.val = typeof(val) == "string" ? val.charCodeAt() : (val | 0)' constructor: 'this.val = typeof(val) == "string" ? val.charCodeAt() : (val | 0)'
value_of: 'this.val | 0' value_of: 'this.val | 0'
to_string: 'String.fromCharCode(this.val)' to_string: 'String.fromCharCode(this.val)'
eq: 'this.valueOf() === other.valueOf()' eq: 'this.valueOf() === other.valueOf()'
}) )
} }
'f32', 'f64', 'float_literal' { 'f32', 'f64', 'float_literal' {
g.gen_builtin_prototype({ g.gen_builtin_prototype(
typ_name: typ_name typ_name: typ_name
default_value: 'new Number(0)' default_value: 'new Number(0)'
}) )
} }
'bool' { 'bool' {
g.gen_builtin_prototype({ g.gen_builtin_prototype(
typ_name: typ_name typ_name: typ_name
default_value: 'new Boolean(false)' default_value: 'new Boolean(false)'
}) )
} }
'string' { 'string' {
g.gen_builtin_prototype({ g.gen_builtin_prototype(
typ_name: typ_name typ_name: typ_name
val_name: 'str' val_name: 'str'
default_value: 'new String("")' default_value: 'new String("")'
@ -294,10 +334,10 @@ fn (mut g JsGen) gen_builtin_type_defs() {
to_string: 'this.str' to_string: 'this.str'
eq: 'this.str === other.str' eq: 'this.str === other.str'
has_strfn: false has_strfn: false
}) )
} }
'map' { 'map' {
g.gen_builtin_prototype({ g.gen_builtin_prototype(
typ_name: typ_name typ_name: typ_name
val_name: 'map' val_name: 'map'
default_value: 'new Map()' default_value: 'new Map()'
@ -305,10 +345,10 @@ fn (mut g JsGen) gen_builtin_type_defs() {
value_of: 'this.map' value_of: 'this.map'
to_string: 'this.map.toString()' to_string: 'this.map.toString()'
eq: 'vEq(this, other)' eq: 'vEq(this, other)'
}) )
} }
'array' { 'array' {
g.gen_builtin_prototype({ g.gen_builtin_prototype(
typ_name: typ_name typ_name: typ_name
val_name: 'arr' val_name: 'arr'
default_value: 'new Array()' default_value: 'new Array()'
@ -316,7 +356,7 @@ fn (mut g JsGen) gen_builtin_type_defs() {
value_of: 'this.arr' value_of: 'this.arr'
to_string: 'JSON.stringify(this.arr.map(it => it.valueOf()))' to_string: 'JSON.stringify(this.arr.map(it => it.valueOf()))'
eq: 'vEq(this, other)' eq: 'vEq(this, other)'
}) )
} }
else {} else {}
} }

View File

@ -2,7 +2,6 @@ module js
import strings import strings
import v.ast import v.ast
import v.table
import v.token import v.token
import v.pref import v.pref
import v.util import v.util
@ -19,7 +18,7 @@ const (
// used to generate type structs // used to generate type structs
v_types = ['i8', 'i16', 'int', 'i64', 'byte', 'u16', 'u32', 'u64', 'f32', 'f64', v_types = ['i8', 'i16', 'int', 'i64', 'byte', 'u16', 'u32', 'u64', 'f32', 'f64',
'int_literal', '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, shallow_equatables = [ast.Kind.i8, .i16, .int, .i64, .byte, .u16, .u32, .u64, .f32, .f64,
.int_literal, .float_literal, .size_t, .bool, .string] .int_literal, .float_literal, .size_t, .bool, .string]
) )
@ -34,7 +33,7 @@ mut:
} }
struct JsGen { struct JsGen {
table &table.Table table &ast.Table
pref &pref.Preferences pref &pref.Preferences
mut: mut:
definitions strings.Builder definitions strings.Builder
@ -58,11 +57,11 @@ 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 []ast.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 &ast.Table, pref &pref.Preferences) string {
mut g := &JsGen{ mut g := &JsGen{
definitions: strings.new_builder(100) definitions: strings.new_builder(100)
table: table table: table
@ -356,7 +355,7 @@ fn (mut g JsGen) stmts(stmts []ast.Stmt) {
fn (mut g JsGen) stmt(node ast.Stmt) { fn (mut g JsGen) stmt(node ast.Stmt) {
g.stmt_start_pos = g.ns.out.len g.stmt_start_pos = g.ns.out.len
match node { match node {
ast.EmptyStmt{} ast.EmptyStmt {}
ast.AsmStmt { ast.AsmStmt {
panic('inline asm is not supported by js') panic('inline asm is not supported by js')
} }
@ -587,7 +586,7 @@ fn (mut g JsGen) expr(node ast.Expr) {
// `user := User{name: 'Bob'}` // `user := User{name: 'Bob'}`
g.gen_struct_init(node) g.gen_struct_init(node)
} }
ast.Type { ast.TypeNode {
// skip: JS has no types // skip: JS has no types
// TODO maybe? // TODO maybe?
} }
@ -697,7 +696,7 @@ 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 := should_cast :=
(g.table.type_kind(stmt.left_types.first()) in js.shallow_equatables) (g.table.type_kind(stmt.left_types.first()) in js.shallow_equatables)
&& (g.cast_stack.len <= 0 || stmt.left_types.first() != g.cast_stack.last()) && (g.cast_stack.len <= 0 || stmt.left_types.first() != g.cast_stack.last())
@ -723,7 +722,7 @@ fn (mut g JsGen) gen_assign_stmt(stmt ast.AssignStmt) {
} }
} }
fn (mut g JsGen) gen_attrs(attrs []table.Attr) { fn (mut g JsGen) gen_attrs(attrs []ast.Attr) {
for attr in attrs { for attr in attrs {
g.writeln('/* [$attr.name] */') g.writeln('/* [$attr.name] */')
} }
@ -875,7 +874,7 @@ fn (mut g JsGen) gen_method_decl(it ast.FnDecl) {
g.fn_decl = voidptr(0) g.fn_decl = voidptr(0)
} }
fn (mut g JsGen) fn_args(args []table.Param, is_variadic bool) { fn (mut g JsGen) fn_args(args []ast.Param, is_variadic bool) {
for i, arg in args { for i, arg in args {
name := g.js_name(arg.name) name := g.js_name(arg.name)
is_varg := i == args.len - 1 && is_variadic is_varg := i == args.len - 1 && is_variadic
@ -1388,7 +1387,7 @@ fn (mut g JsGen) gen_index_expr(expr ast.IndexExpr) {
// TODO Does this cover all cases? // TODO Does this cover all cases?
g.expr(expr.left) g.expr(expr.left)
g.write('[') g.write('[')
g.cast_stack << table.int_type_idx g.cast_stack << ast.int_type_idx
g.expr(expr.index) g.expr(expr.index)
g.cast_stack.delete_last() g.cast_stack.delete_last()
g.write(']') g.write(']')
@ -1480,52 +1479,52 @@ fn (mut g JsGen) gen_infix_expr(it ast.InfixExpr) {
} }
} }
fn (mut g JsGen) greater_typ(left table.Type, right table.Type) table.Type { fn (mut g JsGen) greater_typ(left ast.Type, right ast.Type) ast.Type {
l := int(left) l := int(left)
r := int(right) r := int(right)
lr := [l, r] lr := [l, r]
if table.string_type_idx in lr { if ast.string_type_idx in lr {
return table.Type(table.string_type_idx) return ast.Type(ast.string_type_idx)
} }
should_float := (l in table.integer_type_idxs && r in table.float_type_idxs) should_float := (l in ast.integer_type_idxs && r in ast.float_type_idxs)
|| (r in table.integer_type_idxs && l in table.float_type_idxs) || (r in ast.integer_type_idxs && l in ast.float_type_idxs)
if should_float { if should_float {
if table.f64_type_idx in lr { if ast.f64_type_idx in lr {
return table.Type(table.f64_type_idx) return ast.Type(ast.f64_type_idx)
} }
if table.f32_type_idx in lr { if ast.f32_type_idx in lr {
return table.Type(table.f32_type_idx) return ast.Type(ast.f32_type_idx)
} }
return table.Type(table.float_literal_type) return ast.Type(ast.float_literal_type)
} }
should_int := (l in table.integer_type_idxs && r in table.integer_type_idxs) should_int := (l in ast.integer_type_idxs && r in ast.integer_type_idxs)
if should_int { if should_int {
// cant add to u64 - if (table.u64_type_idx in lr) { return table.Type(table.u64_type_idx) } // cant add to u64 - if (ast.u64_type_idx in lr) { return ast.Type(ast.u64_type_idx) }
// just guessing this order // just guessing this order
if table.i64_type_idx in lr { if ast.i64_type_idx in lr {
return table.Type(table.i64_type_idx) return ast.Type(ast.i64_type_idx)
} }
if table.u32_type_idx in lr { if ast.u32_type_idx in lr {
return table.Type(table.u32_type_idx) return ast.Type(ast.u32_type_idx)
} }
if table.int_type_idx in lr { if ast.int_type_idx in lr {
return table.Type(table.int_type_idx) return ast.Type(ast.int_type_idx)
} }
if table.u16_type_idx in lr { if ast.u16_type_idx in lr {
return table.Type(table.u16_type_idx) return ast.Type(ast.u16_type_idx)
} }
if table.i16_type_idx in lr { if ast.i16_type_idx in lr {
return table.Type(table.i16_type_idx) return ast.Type(ast.i16_type_idx)
} }
if table.byte_type_idx in lr { if ast.byte_type_idx in lr {
return table.Type(table.byte_type_idx) return ast.Type(ast.byte_type_idx)
} }
if table.i8_type_idx in lr { if ast.i8_type_idx in lr {
return table.Type(table.i8_type_idx) return ast.Type(ast.i8_type_idx)
} }
return table.Type(table.int_literal_type_idx) return ast.Type(ast.int_literal_type_idx)
} }
return table.Type(l) return ast.Type(l)
} }
fn (mut g JsGen) gen_map_init_expr(it ast.MapInit) { fn (mut g JsGen) gen_map_init_expr(it ast.MapInit) {
@ -1561,7 +1560,7 @@ fn (mut g JsGen) gen_selector_expr(it ast.SelectorExpr) {
} }
fn (mut g JsGen) gen_string_inter_literal(it ast.StringInterLiteral) { fn (mut g JsGen) gen_string_inter_literal(it ast.StringInterLiteral) {
should_cast := !(g.cast_stack.len > 0 && g.cast_stack.last() == table.string_type_idx) should_cast := !(g.cast_stack.len > 0 && g.cast_stack.last() == ast.string_type_idx)
if should_cast { if should_cast {
if g.file.mod.name == 'builtin' { if g.file.mod.name == 'builtin' {
g.write('new ') g.write('new ')
@ -1600,7 +1599,7 @@ fn (mut g JsGen) gen_string_inter_literal(it ast.StringInterLiteral) {
fn (mut g JsGen) gen_string_literal(it ast.StringLiteral) { fn (mut g JsGen) gen_string_literal(it ast.StringLiteral) {
text := it.val.replace("'", "\\'") text := it.val.replace("'", "\\'")
should_cast := !(g.cast_stack.len > 0 && g.cast_stack.last() == table.string_type_idx) should_cast := !(g.cast_stack.len > 0 && g.cast_stack.last() == ast.string_type_idx)
if should_cast { if should_cast {
if g.file.mod.name == 'builtin' { if g.file.mod.name == 'builtin' {
g.write('new ') g.write('new ')
@ -1639,11 +1638,11 @@ fn (mut g JsGen) gen_typeof_expr(it ast.TypeOf) {
if sym.kind == .sum_type { if sym.kind == .sum_type {
// TODO: JS sumtypes not implemented yet // TODO: JS sumtypes not implemented yet
} else if sym.kind == .array_fixed { } else if sym.kind == .array_fixed {
fixed_info := sym.info as table.ArrayFixed fixed_info := sym.info as ast.ArrayFixed
typ_name := g.table.get_type_name(fixed_info.elem_type) typ_name := g.table.get_type_name(fixed_info.elem_type)
g.write('"[$fixed_info.size]$typ_name"') g.write('"[$fixed_info.size]$typ_name"')
} else if sym.kind == .function { } else if sym.kind == .function {
info := sym.info as table.FnType info := sym.info as ast.FnType
fn_info := info.func fn_info := info.func
mut repr := 'fn (' mut repr := 'fn ('
for i, arg in fn_info.params { for i, arg in fn_info.params {
@ -1653,7 +1652,7 @@ fn (mut g JsGen) gen_typeof_expr(it ast.TypeOf) {
repr += g.table.get_type_name(arg.typ) repr += g.table.get_type_name(arg.typ)
} }
repr += ')' repr += ')'
if fn_info.return_type != table.void_type { if fn_info.return_type != ast.void_type {
repr += ' ${g.table.get_type_name(fn_info.return_type)}' repr += ' ${g.table.get_type_name(fn_info.return_type)}'
} }
g.write('"$repr"') g.write('"$repr"')
@ -1663,8 +1662,8 @@ fn (mut g JsGen) gen_typeof_expr(it ast.TypeOf) {
} }
fn (mut g JsGen) gen_type_cast_expr(it ast.CastExpr) { fn (mut g JsGen) gen_type_cast_expr(it ast.CastExpr) {
is_literal := ((it.expr is ast.IntegerLiteral && it.typ in table.integer_type_idxs) is_literal := ((it.expr is ast.IntegerLiteral && it.typ in ast.integer_type_idxs)
|| (it.expr is ast.FloatLiteral && it.typ in table.float_type_idxs)) || (it.expr is ast.FloatLiteral && it.typ in ast.float_type_idxs))
// Skip cast if type is the same as the parrent caster // Skip cast if type is the same as the parrent caster
if g.cast_stack.len > 0 && is_literal { if g.cast_stack.len > 0 && is_literal {
if it.typ == g.cast_stack[g.cast_stack.len - 1] { if it.typ == g.cast_stack[g.cast_stack.len - 1] {
@ -1690,7 +1689,7 @@ fn (mut g JsGen) gen_type_cast_expr(it ast.CastExpr) {
} }
fn (mut g JsGen) gen_integer_literal_expr(it ast.IntegerLiteral) { fn (mut g JsGen) gen_integer_literal_expr(it ast.IntegerLiteral) {
typ := table.Type(table.int_type) typ := ast.Type(ast.int_type)
// Don't wrap integers for use in JS.foo functions. // Don't wrap integers for use in JS.foo functions.
// TODO: call.language always seems to be "v", parser bug? // TODO: call.language always seems to be "v", parser bug?
@ -1710,7 +1709,7 @@ fn (mut g JsGen) gen_integer_literal_expr(it ast.IntegerLiteral) {
// Skip cast if type is the same as the parrent caster // Skip cast if type is the same as the parrent caster
if g.cast_stack.len > 0 { if g.cast_stack.len > 0 {
if g.cast_stack[g.cast_stack.len - 1] in table.integer_type_idxs { if g.cast_stack[g.cast_stack.len - 1] in ast.integer_type_idxs {
g.write('$it.val') g.write('$it.val')
return return
} }
@ -1724,7 +1723,7 @@ fn (mut g JsGen) gen_integer_literal_expr(it ast.IntegerLiteral) {
} }
fn (mut g JsGen) gen_float_literal_expr(it ast.FloatLiteral) { fn (mut g JsGen) gen_float_literal_expr(it ast.FloatLiteral) {
typ := table.Type(table.f32_type) typ := ast.Type(ast.f32_type)
// Don't wrap integers for use in JS.foo functions. // Don't wrap integers for use in JS.foo functions.
// TODO: call.language always seems to be "v", parser bug? // TODO: call.language always seems to be "v", parser bug?
@ -1734,7 +1733,7 @@ fn (mut g JsGen) gen_float_literal_expr(it ast.FloatLiteral) {
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 ast.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)
@ -1748,10 +1747,10 @@ fn (mut g JsGen) gen_float_literal_expr(it ast.FloatLiteral) {
// Skip cast if type is the same as the parrent caster // Skip cast if type is the same as the parrent caster
if g.cast_stack.len > 0 { if g.cast_stack.len > 0 {
if g.cast_stack[g.cast_stack.len - 1] in table.float_type_idxs { if g.cast_stack[g.cast_stack.len - 1] in ast.float_type_idxs {
g.write('$it.val') g.write('$it.val')
return return
} else if g.cast_stack[g.cast_stack.len - 1] in table.integer_type_idxs { } else if g.cast_stack[g.cast_stack.len - 1] in ast.integer_type_idxs {
g.write(int(it.val.f64()).str()) g.write(int(it.val.f64()).str())
return return
} }

View File

@ -4,7 +4,7 @@ import v.ast
struct JsDoc { struct JsDoc {
mut: mut:
gen &JsGen gen &JsGen
} }
fn new_jsdoc(gen &JsGen) &JsDoc { fn new_jsdoc(gen &JsGen) &JsDoc {
@ -14,12 +14,16 @@ fn new_jsdoc(gen &JsGen) &JsDoc {
} }
fn (mut d JsDoc) write(s string) { fn (mut d JsDoc) write(s string) {
if !d.gen.enable_doc { return } if !d.gen.enable_doc {
return
}
d.gen.write(s) d.gen.write(s)
} }
fn (mut d JsDoc) writeln(s string) { fn (mut d JsDoc) writeln(s string) {
if !d.gen.enable_doc { return } if !d.gen.enable_doc {
return
}
d.gen.writeln(s) d.gen.writeln(s)
} }
@ -45,7 +49,9 @@ fn (mut d JsDoc) gen_fac_fn(fields []ast.StructField) {
// Marked as optional: structs have default default values, // Marked as optional: structs have default default values,
// so all struct members don't have to be initialized. // so all struct members don't have to be initialized.
d.write('$field.name?: ${d.gen.typ(field.typ)}') d.write('$field.name?: ${d.gen.typ(field.typ)}')
if i < fields.len - 1 { d.write(', ') } if i < fields.len - 1 {
d.write(', ')
}
} }
d.writeln('}} init') d.writeln('}} init')
d.writeln('*/') d.writeln('*/')

View File

@ -7,7 +7,7 @@ const (
) )
fn testsuite_end() { fn testsuite_end() {
os.rmdir_all(output_dir) or { } os.rmdir_all(output_dir) or {}
} }
const there_is_node_available = is_nodejs_working() const there_is_node_available = is_nodejs_working()

View File

@ -69,4 +69,4 @@ function vEq(a, b) {
return a!==a && b!==b; return a!==a && b!==b;
}; };
" "
) )

View File

@ -1,5 +1,10 @@
fn map_cb(s string) string { return 'CB: $s' } fn map_cb(s string) string {
fn filter_cb(n int) bool { return n < 4 } return 'CB: $s'
}
fn filter_cb(n int) bool {
return n < 4
}
fn variadic(args ...int) { fn variadic(args ...int) {
println(args) println(args)
@ -13,111 +18,119 @@ fn vararg_test() {
// TODO Remove `fn main` once vet supports scripts // TODO Remove `fn main` once vet supports scripts
fn main() { fn main() {
vararg_test() vararg_test()
arr1 := ['Hello', 'JS', 'Backend'] arr1 := ['Hello', 'JS', 'Backend']
mut arr2 := [1, 2, 3, 4, 5] mut arr2 := [1, 2, 3, 4, 5]
// Array slices // Array slices
slice1 := arr1[1..3] slice1 := arr1[1..3]
slice2 := arr2[..3] slice2 := arr2[..3]
slice3 := arr2[3..] slice3 := arr2[3..]
// Array indexes // Array indexes
idx1 := slice1[1] idx1 := slice1[1]
arr2[0] = 1 arr2[0] = 1
arr2[0 + 1] = 2 arr2[0 + 1] = 2
println(arr2) println(arr2)
// TODO: This does not work for now // TODO: This does not work for now
// arr2[0..1] = arr2[3..4] // arr2[0..1] = arr2[3..4]
// println(arr2) // println(arr2)
// Array push operator // Array push operator
arr2 << 6 arr2 << 6
arr2 << [7, 8, 9] arr2 << [7, 8, 9]
println(arr2) println(arr2)
println('\n\n') println('\n\n')
// String slices // String slices
mut slice4 := idx1[..4] mut slice4 := idx1[..4]
print('Back\t=> ') print('Back\t=> ')
println(slice4) // 'Back' println(slice4) // 'Back'
// String indexes // String indexes
idx2 := slice4[0] idx2 := slice4[0]
print('66\t=> ') print('66\t=> ')
println(idx2) println(idx2)
// TODO: // TODO:
// slice4[3] = `c` // slice4[3] = `c`
// Maps // Maps
mut m := map[string]string mut m := map[string]string{}
key := 'key' key := 'key'
m[key] = 'value' m[key] = 'value'
val := m['key'] val := m['key']
print('value\t=> ') print('value\t=> ')
println(val) println(val)
// 'in' / '!in' // 'in' / '!in'
print('true\t=> ') print('true\t=> ')
println('JS' in arr1) println('JS' in arr1)
print('false\t=> ') print('false\t=> ')
println(3 !in arr2) println(3 !in arr2)
print('true\t=> ') print('true\t=> ')
println('key' in m) println('key' in m)
print('true\t=> ') print('true\t=> ')
println('badkey' !in m) println('badkey' !in m)
print('true\t=> ') print('true\t=> ')
println('o' in 'hello') println('o' in 'hello')
// for in // for in
for _ in arr1 {} for _ in arr1 {}
println('0 to 8\t=>') println('0 to 8\t=>')
for i, _ in arr2 { println(i) } for i, _ in arr2 {
println('\n\n4 to 5\t=> ') println(i)
for _, v in slice3 { println(v) } }
println('\n\n4 to 5\t=> ')
for _, v in slice3 {
println(v)
}
println(int(1.5)) println(int(1.5))
println('\n\n') println('\n\n')
// map // map
a := arr1.map('VAL: $it') a := arr1.map('VAL: $it')
b := arr1.map(map_cb) b := arr1.map(map_cb)
c := arr1.map(map_cb(it)) c := arr1.map(map_cb(it))
d := arr1.map(fn(a string) string { return 'ANON: $a' }) d := arr1.map(fn (a string) string {
// I don't know when this would ever be used, return 'ANON: $a'
// but it's what the C backend does ¯\_(ツ)_/¯ })
e := arr1.map(456) // I don't know when this would ever be used,
// but it's what the C backend does ¯\_(ツ)_/¯
e := arr1.map(456)
println(a) println(a)
println(b) println(b)
println(c) println(c)
println(d) println(d)
println(e) println(e)
println('\n\n') println('\n\n')
// filter // filter
aa := arr2.filter(it < 4) aa := arr2.filter(it < 4)
bb := arr2.filter(filter_cb) bb := arr2.filter(filter_cb)
cc := arr2.filter(filter_cb(it)) cc := arr2.filter(filter_cb(it))
dd := arr2.filter(fn(a int) bool { return a < 4 }) dd := arr2.filter(fn (a int) bool {
return a < 4
})
println(aa) println(aa)
println(bb) println(bb)
println(cc) println(cc)
println(dd) println(dd)
// fixed arrays: implemented as normal arrays // fixed arrays: implemented as normal arrays
f1 := [1, 2, 3, 4, 5]! f1 := [1, 2, 3, 4, 5]!
mut f2 := [8]f32 mut f2 := [8]f32{}
f2[0] = f32(1.23) f2[0] = f32(1.23)
f3 := ['foo', 'bar']! f3 := ['foo', 'bar']!
f4 := [u64(0xffffffffffffffff), 0xdeadface]! f4 := [u64(0xffffffffffffffff), 0xdeadface]!
println(' println('
$f1 $f1
$f2 $f2
$f3 $f3

View File

@ -1,4 +1,4 @@
import hello import v.gen.js.tests.hello
enum Test { enum Test {
foo = 2 foo = 2
@ -8,13 +8,12 @@ enum Test {
// TODO Remove `fn main` once vet supports scripts // TODO Remove `fn main` once vet supports scripts
fn main() { fn main() {
mut a := hello.Ccc.a mut a := hello.Ccc.a
a = .b a = .b
a = .c a = .c
println(a) println(a)
mut b := Test.foo
mut b := Test.foo b = .bar
b = .bar println(b)
println(b)
} }

View File

@ -1,6 +1,6 @@
module hello module hello
import hello.hello1 import v.gen.js.tests.hello.hello1
pub const ( pub const (
hello = 'Hello' hello = 'Hello'
@ -25,9 +25,9 @@ pub enum Ccc {
pub fn debugger() string { pub fn debugger() string {
v := Bbb{} v := Bbb{}
return hello return hello.hello
} }
pub fn excited() string { pub fn excited() string {
return "$hello1.nested() $debugger()!" return '$hello1.nested() $debugger()!'
} }

View File

@ -1,5 +1,5 @@
fn test_fn(s1, s2 string) { fn test_fn(s1 string, s2 string) {
print(if s1 == s2 {'true'} else {'false'}) print(if s1 == s2 { 'true' } else { 'false' })
print('\t=> ') print('\t=> ')
println('"$s1", "$s2"') println('"$s1", "$s2"')
} }
@ -60,7 +60,7 @@ fn implicit_str() {
test_fn('int $i', 'int 42') test_fn('int $i', 'int 42')
test_fn('$i', '42') test_fn('$i', '42')
check := '$i' == '42' check := '$i' == '42'
//println(check) // println(check)
text := '$i' + '42' text := '$i' + '42'
test_fn(text, '4242') test_fn(text, '4242')
} }
@ -89,9 +89,9 @@ fn interpolation_string_prefix_expr() {
r := 1 r := 1
c := 2 c := 2
js := 1 js := 1
test_fn('>${3+r}<', '>4<') test_fn('>${3 + r}<', '>4<')
test_fn('${r == js} $js', 'true 1') test_fn('${r == js} $js', 'true 1')
test_fn('>${js+c} ${js+r==c}<', '>3 true<') test_fn('>${js + c} ${js + r == c}<', '>3 true<')
} }
/* /*
@ -134,8 +134,8 @@ fn utf8_string_interpolation() {
test_fn('$a $st $m', 'à-côté Sträßle 10') test_fn('$a $st $m', 'à-côté Sträßle 10')
zz := '>${a:10}< >${st:-8}< >${m:5}<-' zz := '>${a:10}< >${st:-8}< >${m:5}<-'
zz_expected := '> à-côté< >Sträßle < > 10<-' zz_expected := '> à-côté< >Sträßle < > 10<-'
//println(' zz: $zz') // println(' zz: $zz')
//println('zz_expected: $zz_expected') // println('zz_expected: $zz_expected')
test_fn(zz, zz_expected) test_fn(zz, zz_expected)
// e := '\u20AC' // Eurosign doesn' work with MSVC and tcc // e := '\u20AC' // Eurosign doesn' work with MSVC and tcc
e := '' e := ''
@ -153,7 +153,7 @@ struct Sss {
} }
fn (s Sss) str() string { fn (s Sss) str() string {
return '[${s.v1}, ${s.v2:.3f}]' return '[$s.v1, ${s.v2:.3f}]'
} }
fn string_interpolation_str_evaluation() { fn string_interpolation_str_evaluation() {

View File

@ -1,5 +1,5 @@
import hello as hl import v.gen.js.tests.hello as hl
import hello.hello1 as hl1 import v.gen.js.tests.hello.hello1 as hl1
const ( const (
i_am_a_const = 21214 i_am_a_const = 21214
@ -71,7 +71,7 @@ fn main() {
arr := [1, 2, 3, 4, 5] arr := [1, 2, 3, 4, 5]
for i in arr { for i in arr {
} }
ma := { ma := map{
'str': 'done' 'str': 'done'
'ddo': 'baba' 'ddo': 'baba'
} }
@ -91,15 +91,14 @@ fn main() {
propagation() or { println(err) } propagation() or { println(err) }
} }
fn anon_consumer(greeting string, anon fn (message string)) { fn anon_consumer(greeting string, anon fn (string)) {
anon(greeting) anon(greeting)
} }
fn async(num int, def string) { fn async(num int, def string) {
} }
[inline] [deprecated; inline]
[deprecated]
fn hello(game_on int, dummy ...string) (int, int) { fn hello(game_on int, dummy ...string) (int, int) {
defer { defer {
do := 'not' do := 'not'
@ -130,7 +129,9 @@ fn (it Companies) method() int {
} }
fn error_if_even(num int) ?int { fn error_if_even(num int) ?int {
if num % 2 == 0 { return error('number is even') } if num % 2 == 0 {
return error('number is even')
}
return num return num
} }

View File

@ -1,24 +1,49 @@
fn clear() { JS.console.clear() } fn clear() {
JS.console.clear()
}
const (w = 30 h = 30) const (
w = 30
h = 30
)
fn get(game [][]bool, x int, y int) bool { fn get(game [][]bool, x int, y int) bool {
if y < 0 || x < 0 { return false } if y < 0 || x < 0 {
if y >= h || x >= w { return false } return false
}
if y >= h || x >= w {
return false
}
return game[y][x] return game[y][x]
} }
fn neighbours(game [][]bool, x int, y int) int { fn neighbours(game [][]bool, x int, y int) int {
mut count := 0 mut count := 0
if get(game, x-1, y-1) { count++ } if get(game, x - 1, y - 1) {
if get(game, x, y-1) { count++ } count++
if get(game, x+1, y-1) { count++ } }
if get(game, x-1, y) { count++ } if get(game, x, y - 1) {
if get(game, x+1, y) { count++ } count++
if get(game, x-1, y+1) { count++ } }
if get(game, x, y+1) { count++ } if get(game, x + 1, y - 1) {
if get(game, x+1, y+1) { count++ } count++
}
if get(game, x - 1, y) {
count++
}
if get(game, x + 1, y) {
count++
}
if get(game, x - 1, y + 1) {
count++
}
if get(game, x, y + 1) {
count++
}
if get(game, x + 1, y + 1) {
count++
}
return count return count
} }
@ -38,8 +63,11 @@ fn step(game [][]bool) [][]bool {
fn row_str(row []bool) string { fn row_str(row []bool) string {
mut str := '' mut str := ''
for cell in row { for cell in row {
if cell { str += ' ' } if cell {
else { str += ' ' } str += ' '
} else {
str += ' '
}
} }
return str return str
} }
@ -53,15 +81,18 @@ fn show(game [][]bool) {
// TODO Remove `fn main` once vet supports scripts // TODO Remove `fn main` once vet supports scripts
fn main() { fn main() {
mut game := [][]bool{ len: h, init: []bool{ len: w } } mut game := [][]bool{len: h, init: []bool{len: w}}
game[11][15] = true game[11][15] = true
game[11][16] = true game[11][16] = true
game[12][16] = true game[12][16] = true
game[10][21] = true game[10][21] = true
game[12][20] = true game[12][20] = true
game[12][21] = true game[12][21] = true
game[12][22] = true game[12][22] = true
JS.setInterval(fn () { show(game) game = step(game) }, 500) JS.setInterval(fn () {
show(game)
game = step(game)
}, 500)
} }

View File

@ -1,28 +1,30 @@
module main module main
fn main() { fn main() {
try_propagation() or { println("captured: $err") } try_propagation() or { println('captured: $err') }
} }
fn try_propagation() ? { fn try_propagation() ? {
try_numbers()? try_numbers() ?
} }
fn try_numbers() ? { fn try_numbers() ? {
for x in 1 .. 10 { for x in 1 .. 10 {
y := error_if_even(x) or { x + 1 } y := error_if_even(x) or { x + 1 }
println("$x rounded to $y") println('$x rounded to $y')
error_if_prime(y)? error_if_prime(y) ?
} }
} }
fn error_if_even(num int) ?int { fn error_if_even(num int) ?int {
if num % 2 == 0 { return error('number is even') } if num % 2 == 0 {
return error('number is even')
}
return num return num
} }
fn error_if_prime(num int) ?int { fn error_if_prime(num int) ?int {
for i in 2..num { for i in 2 .. num {
if num % i == 0 { if num % i == 0 {
return error('$num is prime') return error('$num is prime')
} }

View File

@ -1,5 +1,5 @@
module main module main
fn main() { fn main() {
println("hello world") println('hello world')
} }

View File

@ -33,8 +33,8 @@ fn main() {
b.add(10) b.add(10)
println(b.get()) // 10 println(b.get()) // 10
use_config(Config{2, 'bar'}) use_config(Config{2, 'bar'})
use_config({ use_config(
foo: 2 foo: 2
bar: 'bar' bar: 'bar'
}) )
} }

View File

@ -10,13 +10,12 @@ import v.errors
import v.pref import v.pref
import term import term
import strings import strings
import v.table
pub struct Gen { pub struct Gen {
out_name string out_name string
pref &pref.Preferences // Preferences shared from V struct pref &pref.Preferences // Preferences shared from V struct
mut: mut:
table &table.Table table &ast.Table
buf []byte buf []byte
sect_header_name_pos int sect_header_name_pos int
offset i64 offset i64
@ -82,7 +81,7 @@ enum Size {
_64 _64
} }
pub fn gen(files []ast.File, table &table.Table, out_name string, pref &pref.Preferences) { pub fn gen(files []ast.File, table &ast.Table, out_name string, pref &pref.Preferences) {
mut g := Gen{ mut g := Gen{
table: table table: table
sect_header_name_pos: 0 sect_header_name_pos: 0
@ -776,7 +775,7 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
sym := g.table.get_type_symbol(right.typ) sym := g.table.get_type_symbol(right.typ)
// println(sym) // println(sym)
// println(typeof(sym.info)) // println(typeof(sym.info))
info := sym.info as table.Struct info := sym.info as ast.Struct
for field in info.fields { for field in info.fields {
field_name := name + '.' + field.name field_name := name + '.' + field.name
println(field_name) println(field_name)

View File

@ -1,12 +1,12 @@
import v.gen.x64 import v.gen.x64
import v.pref import v.pref
import v.table import v.ast
fn test_macho() { fn test_macho() {
mut g := x64.Gen{ mut g := x64.Gen{
pref: &pref.Preferences{} pref: &pref.Preferences{}
out_name: 'test.bin' out_name: 'test.bin'
table: &table.Table{} table: &ast.Table{}
} }
g.generate_macho_header() g.generate_macho_header()
g.generate_macho_footer() g.generate_macho_footer()

View File

@ -3,12 +3,11 @@
module markused module markused
import v.ast import v.ast
import v.table
import v.util import v.util
import v.pref import v.pref
// mark_used walks the AST, starting at main() and marks all used fns transitively // mark_used walks the AST, starting at main() and marks all used fns transitively
pub fn mark_used(mut the_table table.Table, pref &pref.Preferences, ast_files []ast.File) { pub fn mark_used(mut t ast.Table, pref &pref.Preferences, ast_files []ast.File) {
mut all_fns, all_consts := all_fn_and_const(ast_files) mut all_fns, all_consts := all_fn_and_const(ast_files)
util.timing_start(@METHOD) util.timing_start(@METHOD)
@ -103,7 +102,7 @@ pub fn mark_used(mut the_table table.Table, pref &pref.Preferences, ast_files []
// implicit string builders are generated in auto_eq_methods.v // implicit string builders are generated in auto_eq_methods.v
mut sb_mut_type := '' mut sb_mut_type := ''
if sbfn := the_table.find_fn('strings.new_builder') { if sbfn := t.find_fn('strings.new_builder') {
sb_mut_type = sbfn.return_type.set_nr_muls(1).str() + '.' sb_mut_type = sbfn.return_type.set_nr_muls(1).str() + '.'
} }
@ -141,7 +140,7 @@ pub fn mark_used(mut the_table table.Table, pref &pref.Preferences, ast_files []
if pref.is_test { if pref.is_test {
all_fn_root_names << 'main.cb_assertion_ok' all_fn_root_names << 'main.cb_assertion_ok'
all_fn_root_names << 'main.cb_assertion_failed' all_fn_root_names << 'main.cb_assertion_failed'
if benched_tests_sym := the_table.find_type('main.BenchedTests') { if benched_tests_sym := t.find_type('main.BenchedTests') {
bts_type := benched_tests_sym.methods[0].params[0].typ bts_type := benched_tests_sym.methods[0].params[0].typ
all_fn_root_names << '${bts_type}.testing_step_start' all_fn_root_names << '${bts_type}.testing_step_start'
all_fn_root_names << '${bts_type}.testing_step_end' all_fn_root_names << '${bts_type}.testing_step_end'
@ -151,7 +150,7 @@ pub fn mark_used(mut the_table table.Table, pref &pref.Preferences, ast_files []
} }
mut walker := Walker{ mut walker := Walker{
table: the_table table: t
files: ast_files files: ast_files
all_fns: all_fns all_fns: all_fns
all_consts: all_consts all_consts: all_consts
@ -181,12 +180,12 @@ pub fn mark_used(mut the_table table.Table, pref &pref.Preferences, ast_files []
} }
} }
the_table.used_fns = walker.used_fns.move() t.used_fns = walker.used_fns.move()
the_table.used_consts = walker.used_consts.move() t.used_consts = walker.used_consts.move()
$if trace_skip_unused ? { $if trace_skip_unused ? {
eprintln('>> the_table.used_fns: $the_table.used_fns.keys()') eprintln('>> t.used_fns: $t.used_fns.keys()')
eprintln('>> the_table.used_consts: $the_table.used_consts.keys()') eprintln('>> t.used_consts: $t.used_consts.keys()')
eprintln('>> walker.n_maps: $walker.n_maps') eprintln('>> walker.n_maps: $walker.n_maps')
} }
} }

View File

@ -5,11 +5,10 @@ module markused
// Walk the entire program starting at fn main and marks used (called) functions. // Walk the entire program starting at fn main and marks used (called) functions.
// Unused functions can be safely skipped by the backends to save CPU time and space. // Unused functions can be safely skipped by the backends to save CPU time and space.
import v.ast import v.ast
import v.table
pub struct Walker { pub struct Walker {
pub mut: pub mut:
table &table.Table table &ast.Table
used_fns map[string]bool // used_fns['println'] == true used_fns map[string]bool // used_fns['println'] == true
used_consts map[string]bool // used_consts['os.args'] == true used_consts map[string]bool // used_consts['os.args'] == true
n_maps int n_maps int
@ -288,11 +287,10 @@ fn (mut w Walker) expr(node ast.Expr) {
ast.StructInit { ast.StructInit {
sym := w.table.get_type_symbol(node.typ) sym := w.table.get_type_symbol(node.typ)
if sym.kind == .struct_ { if sym.kind == .struct_ {
info := sym.info as table.Struct info := sym.info as ast.Struct
for ifield in info.fields { for ifield in info.fields {
if ifield.has_default_expr { if ifield.has_default_expr {
defex := ast.fe2ex(ifield.default_expr) w.expr(ifield.default_expr)
w.expr(defex)
} }
} }
} }
@ -337,7 +335,7 @@ fn (mut w Walker) expr(node ast.Expr) {
w.stmts(branch.stmts) w.stmts(branch.stmts)
} }
} }
ast.Type {} ast.TypeNode {}
ast.UnsafeExpr { ast.UnsafeExpr {
w.expr(node.expr) w.expr(node.expr)
} }

View File

@ -4,7 +4,6 @@
module parser module parser
import v.ast import v.ast
import v.table
fn (mut p Parser) assign_stmt() ast.Stmt { fn (mut p Parser) assign_stmt() ast.Stmt {
exprs, comments := p.expr_list() exprs, comments := p.expr_list()
@ -134,7 +133,7 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
if p.scope.known_var(lx.name) { if p.scope.known_var(lx.name) {
return p.error_with_pos('redefinition of `$lx.name`', lx.pos) return p.error_with_pos('redefinition of `$lx.name`', lx.pos)
} }
mut share := table.ShareType(0) mut share := ast.ShareType(0)
if lx.info is ast.IdentVar { if lx.info is ast.IdentVar {
iv := lx.info as ast.IdentVar iv := lx.info as ast.IdentVar
share = iv.share share = iv.share

View File

@ -6,7 +6,6 @@ module parser
import os import os
import v.ast import v.ast
import v.pref import v.pref
import v.table
import v.token import v.token
const ( const (

View File

@ -4,15 +4,14 @@
module parser module parser
import v.ast import v.ast
import v.table
fn (mut p Parser) array_init() ast.ArrayInit { fn (mut p Parser) array_init() ast.ArrayInit {
first_pos := p.tok.position() first_pos := p.tok.position()
mut last_pos := p.tok.position() mut last_pos := p.tok.position()
p.check(.lsbr) p.check(.lsbr)
// p.warn('array_init() exp=$p.expected_type') // p.warn('array_init() exp=$p.expected_type')
mut array_type := table.void_type mut array_type := ast.void_type
mut elem_type := table.void_type mut elem_type := ast.void_type
mut elem_type_pos := first_pos mut elem_type_pos := first_pos
mut exprs := []ast.Expr{} mut exprs := []ast.Expr{}
mut ecmnts := [][]ast.Comment{} mut ecmnts := [][]ast.Comment{}
@ -34,7 +33,7 @@ fn (mut p Parser) array_init() ast.ArrayInit {
// this is set here because it's a known type, others could be the // this is set here because it's a known type, others could be the
// result of expr so we do those in checker // result of expr so we do those in checker
idx := p.table.find_or_register_array(elem_type) idx := p.table.find_or_register_array(elem_type)
array_type = table.new_type(idx) array_type = ast.new_type(idx)
has_type = true has_type = true
} }
last_pos = p.tok.position() last_pos = p.tok.position()
@ -105,7 +104,7 @@ fn (mut p Parser) array_init() ast.ArrayInit {
mut has_cap := false mut has_cap := false
mut len_expr := ast.empty_expr() mut len_expr := ast.empty_expr()
mut cap_expr := ast.empty_expr() mut cap_expr := ast.empty_expr()
if p.tok.kind == .lcbr && exprs.len == 0 && array_type != table.void_type { if p.tok.kind == .lcbr && exprs.len == 0 && array_type != ast.void_type {
// `[]int{ len: 10, cap: 100}` syntax // `[]int{ len: 10, cap: 100}` syntax
p.next() p.next()
for p.tok.kind != .rcbr { for p.tok.kind != .rcbr {

View File

@ -4,11 +4,10 @@
module parser module parser
import v.ast import v.ast
import v.table
import v.token import v.token
import v.util import v.util
pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExpr { pub fn (mut p Parser) call_expr(language ast.Language, mod string) ast.CallExpr {
first_pos := p.tok.position() first_pos := p.tok.position()
mut fn_name := if language == .c { mut fn_name := if language == .c {
'C.$p.check_name()' 'C.$p.check_name()'
@ -34,7 +33,7 @@ pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExp
} }
p.expr_mod = '' p.expr_mod = ''
// //
mut generic_types := []table.Type{} mut generic_types := []ast.Type{}
mut generic_list_pos := p.tok.position() mut generic_list_pos := p.tok.position()
if p.tok.kind == .lt { if p.tok.kind == .lt {
// `foo<int>(10)` // `foo<int>(10)`
@ -69,7 +68,7 @@ pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExp
p.open_scope() p.open_scope()
p.scope.register(ast.Var{ p.scope.register(ast.Var{
name: 'err' name: 'err'
typ: table.error_type typ: ast.error_type
pos: p.tok.position() pos: p.tok.position()
is_used: true is_used: true
}) })
@ -150,7 +149,7 @@ pub fn (mut p Parser) call_args() []ast.CallArg {
comments << p.eat_comments({}) comments << p.eat_comments({})
args << ast.CallArg{ args << ast.CallArg{
is_mut: is_mut is_mut: is_mut
share: table.sharetype_from_flags(is_shared, is_atomic) share: ast.sharetype_from_flags(is_shared, is_atomic)
expr: expr expr: expr
comments: comments comments: comments
pos: pos pos: pos
@ -166,10 +165,10 @@ struct ReceiverParsingInfo {
mut: mut:
name string name string
pos token.Position pos token.Position
typ table.Type typ ast.Type
type_pos token.Position type_pos token.Position
is_mut bool is_mut bool
language table.Language language ast.Language
} }
fn (mut p Parser) fn_decl() ast.FnDecl { fn (mut p Parser) fn_decl() ast.FnDecl {
@ -187,12 +186,12 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
p.check(.key_fn) p.check(.key_fn)
p.open_scope() p.open_scope()
// C. || JS. // C. || JS.
mut language := table.Language.v mut language := ast.Language.v
if p.tok.kind == .name && p.tok.lit == 'C' { if p.tok.kind == .name && p.tok.lit == 'C' {
is_unsafe = !p.attrs.contains('trusted') is_unsafe = !p.attrs.contains('trusted')
language = table.Language.c language = ast.Language.c
} else if p.tok.kind == .name && p.tok.lit == 'JS' { } else if p.tok.kind == .name && p.tok.lit == 'JS' {
language = table.Language.js language = ast.Language.js
} }
if language != .v { if language != .v {
p.next() p.next()
@ -201,11 +200,11 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
} }
// Receiver? // Receiver?
mut rec := ReceiverParsingInfo{ mut rec := ReceiverParsingInfo{
typ: table.void_type typ: ast.void_type
language: language language: language
} }
mut is_method := false mut is_method := false
mut params := []table.Param{} mut params := []ast.Param{}
if p.tok.kind == .lpar { if p.tok.kind == .lpar {
is_method = true is_method = true
p.fn_receiver(mut params, mut rec) or { return ast.FnDecl{ p.fn_receiver(mut params, mut rec) or { return ast.FnDecl{
@ -233,7 +232,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
mut is_duplicate := type_sym.has_method(name) mut is_duplicate := type_sym.has_method(name)
// make sure this is a normal method and not an interface method // make sure this is a normal method and not an interface method
if type_sym.kind == .interface_ && is_duplicate { if type_sym.kind == .interface_ && is_duplicate {
if type_sym.info is table.Interface { if type_sym.info is ast.Interface {
// if the method is in info then its an interface method // if the method is in info then its an interface method
is_duplicate = !type_sym.info.has_method(name) is_duplicate = !type_sym.info.has_method(name)
} }
@ -254,7 +253,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
} }
} else if p.tok.kind in [.plus, .minus, .mul, .div, .mod, .lt, .eq] && p.peek_tok.kind == .lpar { } else if p.tok.kind in [.plus, .minus, .mul, .div, .mod, .lt, .eq] && p.peek_tok.kind == .lpar {
name = p.tok.kind.str() // op_to_fn_name() name = p.tok.kind.str() // op_to_fn_name()
if rec.typ == table.void_type { if rec.typ == ast.void_type {
p.error_with_pos('cannot use operator overloading with normal functions', p.error_with_pos('cannot use operator overloading with normal functions',
p.tok.position()) p.tok.position())
} }
@ -294,7 +293,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
} }
} }
// Return type // Return type
mut return_type := table.void_type mut return_type := ast.void_type
// don't confuse token on the next line: fn decl, [attribute] // don't confuse token on the next line: fn decl, [attribute]
same_line := p.tok.line_nr == p.prev_tok.line_nr same_line := p.tok.line_nr == p.prev_tok.line_nr
if (p.tok.kind.is_start_of_type() && (same_line || p.tok.kind != .lsbr)) if (p.tok.kind.is_start_of_type() && (same_line || p.tok.kind != .lsbr))
@ -327,7 +326,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
scope: 0 scope: 0
} }
} }
type_sym_method_idx = type_sym.register_method(table.Fn{ type_sym_method_idx = type_sym.register_method(ast.Fn{
name: name name: name
params: params params: params
return_type: return_type return_type: return_type
@ -355,7 +354,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
if !p.pref.translated && language == .v && name in p.table.fns { if !p.pref.translated && language == .v && name in p.table.fns {
p.table.redefined_fns << name p.table.redefined_fns << name
} }
p.table.register_fn(table.Fn{ p.table.register_fn(ast.Fn{
name: name name: name
params: params params: params
return_type: return_type return_type: return_type
@ -408,7 +407,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
is_main: is_main is_main: is_main
is_test: is_test is_test: is_test
is_conditional: is_conditional is_conditional: is_conditional
receiver: ast.Field{ receiver: ast.StructField{
name: rec.name name: rec.name
typ: rec.typ typ: rec.typ
} }
@ -433,7 +432,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
return fn_decl return fn_decl
} }
fn (mut p Parser) fn_receiver(mut params []table.Param, mut rec ReceiverParsingInfo) ? { fn (mut p Parser) fn_receiver(mut params []ast.Param, mut rec ReceiverParsingInfo) ? {
lpar_pos := p.tok.position() lpar_pos := p.tok.position()
p.next() // ( p.next() // (
is_shared := p.tok.kind == .key_shared is_shared := p.tok.kind == .key_shared
@ -458,7 +457,7 @@ fn (mut p Parser) fn_receiver(mut params []table.Param, mut rec ReceiverParsingI
rec.pos = rec_start_pos.extend(p.tok.position()) rec.pos = rec_start_pos.extend(p.tok.position())
is_amp := p.tok.kind == .amp is_amp := p.tok.kind == .amp
if p.tok.kind == .name && p.tok.lit == 'JS' { if p.tok.kind == .name && p.tok.lit == 'JS' {
rec.language = table.Language.js rec.language = ast.Language.js
} }
// if rec.is_mut { // if rec.is_mut {
// p.check(.key_mut) // p.check(.key_mut)
@ -487,14 +486,14 @@ fn (mut p Parser) fn_receiver(mut params []table.Param, mut rec ReceiverParsingI
type_sym := p.table.get_type_symbol(rec.typ) type_sym := p.table.get_type_symbol(rec.typ)
mut is_auto_rec := false mut is_auto_rec := false
if type_sym.kind == .struct_ { if type_sym.kind == .struct_ {
info := type_sym.info as table.Struct info := type_sym.info as ast.Struct
if !rec.is_mut && !rec.typ.is_ptr() && info.fields.len > 8 { if !rec.is_mut && !rec.typ.is_ptr() && info.fields.len > 8 {
rec.typ = rec.typ.to_ptr() rec.typ = rec.typ.to_ptr()
is_auto_rec = true is_auto_rec = true
} }
} }
params << table.Param{ params << ast.Param{
pos: rec_start_pos pos: rec_start_pos
name: rec.name name: rec.name
is_mut: rec.is_mut is_mut: rec.is_mut
@ -574,7 +573,7 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
}) })
} }
mut same_line := p.tok.line_nr == p.prev_tok.line_nr mut same_line := p.tok.line_nr == p.prev_tok.line_nr
mut return_type := table.void_type mut return_type := ast.void_type
// lpar: multiple return types // lpar: multiple return types
if same_line { if same_line {
if p.tok.kind.is_start_of_type() { if p.tok.kind.is_start_of_type() {
@ -592,7 +591,7 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
p.tok.position()) p.tok.position())
} }
mut label_names := []string{} mut label_names := []string{}
mut func := table.Fn{ mut func := ast.Fn{
params: args params: args
is_variadic: is_variadic is_variadic: is_variadic
return_type: return_type return_type: return_type
@ -611,7 +610,7 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
p.close_scope() p.close_scope()
func.name = name func.name = name
idx := p.table.find_or_register_fn_type(p.mod, func, true, false) idx := p.table.find_or_register_fn_type(p.mod, func, true, false)
typ := table.new_type(idx) typ := ast.new_type(idx)
// name := p.table.get_type_name(typ) // name := p.table.get_type_name(typ)
return ast.AnonFn{ return ast.AnonFn{
decl: ast.FnDecl{ decl: ast.FnDecl{
@ -634,9 +633,9 @@ fn (mut p Parser) anon_fn() ast.AnonFn {
} }
// part of fn declaration // part of fn declaration
fn (mut p Parser) fn_args() ([]table.Param, bool, bool) { fn (mut p Parser) fn_args() ([]ast.Param, bool, bool) {
p.check(.lpar) p.check(.lpar)
mut args := []table.Param{} mut args := []ast.Param{}
mut is_variadic := false mut is_variadic := false
// `int, int, string` (no names, just types) // `int, int, string` (no names, just types)
argname := if p.tok.kind == .name && p.tok.lit.len > 0 && p.tok.lit[0].is_capital() { argname := if p.tok.kind == .name && p.tok.lit.len > 0 && p.tok.lit[0].is_capital() {
@ -653,7 +652,7 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
for p.tok.kind != .rpar { for p.tok.kind != .rpar {
if p.tok.kind == .eof { if p.tok.kind == .eof {
p.error_with_pos('expecting `)`', p.tok.position()) p.error_with_pos('expecting `)`', p.tok.position())
return []table.Param{}, false, false return []ast.Param{}, false, false
} }
is_shared := p.tok.kind == .key_shared is_shared := p.tok.kind == .key_shared
is_atomic := p.tok.kind == .key_atomic is_atomic := p.tok.kind == .key_atomic
@ -669,7 +668,7 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
mut arg_type := p.parse_type() mut arg_type := p.parse_type()
if arg_type == 0 { if arg_type == 0 {
// error is added in parse_type // error is added in parse_type
return []table.Param{}, false, false return []ast.Param{}, false, false
} }
if is_mut { if is_mut {
if !arg_type.has_flag(.generic) { if !arg_type.has_flag(.generic) {
@ -682,7 +681,7 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
} }
} else if is_shared || is_atomic { } else if is_shared || is_atomic {
p.error_with_pos('generic object cannot be `atomic`or `shared`', pos) p.error_with_pos('generic object cannot be `atomic`or `shared`', pos)
return []table.Param{}, false, false return []ast.Param{}, false, false
} }
// if arg_type.is_ptr() { // if arg_type.is_ptr() {
// p.error('cannot mut') // p.error('cannot mut')
@ -697,21 +696,21 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
} }
} }
if is_variadic { if is_variadic {
arg_type = table.new_type(p.table.find_or_register_array(arg_type)).set_flag(.variadic) arg_type = ast.new_type(p.table.find_or_register_array(arg_type)).set_flag(.variadic)
} }
if p.tok.kind == .eof { if p.tok.kind == .eof {
p.error_with_pos('expecting `)`', p.prev_tok.position()) p.error_with_pos('expecting `)`', p.prev_tok.position())
return []table.Param{}, false, false return []ast.Param{}, false, false
} }
if p.tok.kind == .comma { if p.tok.kind == .comma {
if is_variadic { if is_variadic {
p.error_with_pos('cannot use ...(variadic) with non-final parameter no $arg_no', p.error_with_pos('cannot use ...(variadic) with non-final parameter no $arg_no',
pos) pos)
return []table.Param{}, false, false return []ast.Param{}, false, false
} }
p.next() p.next()
} }
args << table.Param{ args << ast.Param{
pos: pos pos: pos
name: '' name: ''
is_mut: is_mut is_mut: is_mut
@ -720,14 +719,14 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
arg_no++ arg_no++
if arg_no > 1024 { if arg_no > 1024 {
p.error_with_pos('too many args', pos) p.error_with_pos('too many args', pos)
return []table.Param{}, false, false return []ast.Param{}, false, false
} }
} }
} else { } else {
for p.tok.kind != .rpar { for p.tok.kind != .rpar {
if p.tok.kind == .eof { if p.tok.kind == .eof {
p.error_with_pos('expecting `)`', p.tok.position()) p.error_with_pos('expecting `)`', p.tok.position())
return []table.Param{}, false, false return []ast.Param{}, false, false
} }
is_shared := p.tok.kind == .key_shared is_shared := p.tok.kind == .key_shared
is_atomic := p.tok.kind == .key_atomic is_atomic := p.tok.kind == .key_atomic
@ -768,7 +767,7 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
mut typ := p.parse_type() mut typ := p.parse_type()
if typ == 0 { if typ == 0 {
// error is added in parse_type // error is added in parse_type
return []table.Param{}, false, false return []ast.Param{}, false, false
} }
if is_mut { if is_mut {
if !typ.has_flag(.generic) { if !typ.has_flag(.generic) {
@ -782,7 +781,7 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
} else if is_shared || is_atomic { } else if is_shared || is_atomic {
p.error_with_pos('generic object cannot be `atomic` or `shared`', p.error_with_pos('generic object cannot be `atomic` or `shared`',
pos) pos)
return []table.Param{}, false, false return []ast.Param{}, false, false
} }
typ = typ.set_nr_muls(1) typ = typ.set_nr_muls(1)
if is_shared { if is_shared {
@ -793,10 +792,10 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
} }
} }
if is_variadic { if is_variadic {
typ = table.new_type(p.table.find_or_register_array(typ)).derive(typ).set_flag(.variadic) typ = ast.new_type(p.table.find_or_register_array(typ)).derive(typ).set_flag(.variadic)
} }
for i, arg_name in arg_names { for i, arg_name in arg_names {
args << table.Param{ args << ast.Param{
pos: arg_pos[i] pos: arg_pos[i]
name: arg_name name: arg_name
is_mut: is_mut is_mut: is_mut
@ -807,12 +806,12 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
if is_variadic && p.tok.kind == .comma { if is_variadic && p.tok.kind == .comma {
p.error_with_pos('cannot use ...(variadic) with non-final parameter $arg_name', p.error_with_pos('cannot use ...(variadic) with non-final parameter $arg_name',
arg_pos[i]) arg_pos[i])
return []table.Param{}, false, false return []ast.Param{}, false, false
} }
} }
if p.tok.kind == .eof { if p.tok.kind == .eof {
p.error_with_pos('expecting `)`', p.prev_tok.position()) p.error_with_pos('expecting `)`', p.prev_tok.position())
return []table.Param{}, false, false return []ast.Param{}, false, false
} }
if p.tok.kind != .rpar { if p.tok.kind != .rpar {
p.check(.comma) p.check(.comma)
@ -823,7 +822,7 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) {
return args, types_only, is_variadic return args, types_only, is_variadic
} }
fn (mut p Parser) check_fn_mutable_arguments(typ table.Type, pos token.Position) { fn (mut p Parser) check_fn_mutable_arguments(typ ast.Type, pos token.Position) {
sym := p.table.get_type_symbol(typ) sym := p.table.get_type_symbol(typ)
if sym.kind in [.array, .array_fixed, .interface_, .map, .placeholder, .struct_, .sum_type] { if sym.kind in [.array, .array_fixed, .interface_, .map, .placeholder, .struct_, .sum_type] {
return return
@ -832,7 +831,7 @@ fn (mut p Parser) check_fn_mutable_arguments(typ table.Type, pos token.Position)
return return
} }
if sym.kind == .alias { if sym.kind == .alias {
atyp := (sym.info as table.Alias).parent_type atyp := (sym.info as ast.Alias).parent_type
p.check_fn_mutable_arguments(atyp, pos) p.check_fn_mutable_arguments(atyp, pos)
return return
} }
@ -842,7 +841,7 @@ fn (mut p Parser) check_fn_mutable_arguments(typ table.Type, pos token.Position)
pos) pos)
} }
fn (mut p Parser) check_fn_shared_arguments(typ table.Type, pos token.Position) { fn (mut p Parser) check_fn_shared_arguments(typ ast.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] && !typ.is_ptr() {
p.error_with_pos('shared arguments are only allowed for arrays, maps, and structs\n', p.error_with_pos('shared arguments are only allowed for arrays, maps, and structs\n',
@ -850,7 +849,7 @@ fn (mut p Parser) check_fn_shared_arguments(typ table.Type, pos token.Position)
} }
} }
fn (mut p Parser) check_fn_atomic_arguments(typ table.Type, pos token.Position) { fn (mut p Parser) check_fn_atomic_arguments(typ ast.Type, pos token.Position) {
sym := p.table.get_type_symbol(typ) sym := p.table.get_type_symbol(typ)
if sym.kind !in [.u32, .int, .u64] { if sym.kind !in [.u32, .int, .u64] {
p.error_with_pos('atomic arguments are only allowed for 32/64 bit integers\n' + p.error_with_pos('atomic arguments are only allowed for 32/64 bit integers\n' +

View File

@ -4,7 +4,6 @@
module parser module parser
import v.ast import v.ast
import v.table
fn (mut p Parser) for_stmt() ast.Stmt { fn (mut p Parser) for_stmt() ast.Stmt {
p.check(.key_for) p.check(.key_for)
@ -120,7 +119,7 @@ fn (mut p Parser) for_stmt() ast.Stmt {
} }
p.scope.register(ast.Var{ p.scope.register(ast.Var{
name: key_var_name name: key_var_name
typ: table.int_type typ: ast.int_type
pos: key_var_pos pos: key_var_pos
is_tmp: true is_tmp: true
}) })
@ -144,7 +143,7 @@ fn (mut p Parser) for_stmt() ast.Stmt {
high_expr = p.expr(0) high_expr = p.expr(0)
p.scope.register(ast.Var{ p.scope.register(ast.Var{
name: val_var_name name: val_var_name
typ: table.int_type typ: ast.int_type
pos: val_var_pos pos: val_var_pos
is_tmp: true is_tmp: true
}) })

View File

@ -4,7 +4,6 @@
module parser module parser
import v.ast import v.ast
import v.table
import v.token import v.token
fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr { fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
@ -52,7 +51,7 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
if prev_guard { if prev_guard {
p.scope.register(ast.Var{ p.scope.register(ast.Var{
name: 'err' name: 'err'
typ: table.error_type typ: ast.error_type
pos: p.tok.position() pos: p.tok.position()
is_used: true is_used: true
}) })
@ -178,16 +177,16 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
is_else = true is_else = true
p.next() p.next()
} else if (p.tok.kind == .name && !(p.tok.lit == 'C' && p.peek_tok.kind == .dot) } else if (p.tok.kind == .name && !(p.tok.lit == 'C' && p.peek_tok.kind == .dot)
&& (p.tok.lit in table.builtin_type_names || p.tok.lit[0].is_capital() && (p.tok.lit in ast.builtin_type_names || p.tok.lit[0].is_capital()
|| (p.peek_tok.kind == .dot && p.peek_token(2).lit.len > 0 || (p.peek_tok.kind == .dot && p.peek_token(2).lit.len > 0
&& p.peek_token(2).lit[0].is_capital()))) || p.tok.kind == .lsbr { && p.peek_token(2).lit[0].is_capital()))) || p.tok.kind == .lsbr {
mut types := []table.Type{} mut types := []ast.Type{}
for { for {
// Sum type match // Sum type match
parsed_type := p.parse_type() parsed_type := p.parse_type()
ecmnts << p.eat_comments({}) ecmnts << p.eat_comments({})
types << parsed_type types << parsed_type
exprs << ast.Type{ exprs << ast.TypeNode{
typ: parsed_type typ: parsed_type
pos: p.prev_tok.position() pos: p.prev_tok.position()
} }

View File

@ -1,7 +1,6 @@
module parser module parser
import v.ast import v.ast
import v.table
fn (mut p Parser) lock_expr() ast.LockExpr { fn (mut p Parser) lock_expr() ast.LockExpr {
// TODO Handle aliasing sync // TODO Handle aliasing sync
@ -20,7 +19,7 @@ fn (mut p Parser) lock_expr() ast.LockExpr {
p.next() p.next()
for p.tok.kind == .name { for p.tok.kind == .name {
lockeds << ast.Ident{ lockeds << ast.Ident{
language: table.Language.v language: ast.Language.v
pos: p.tok.position() pos: p.tok.position()
mod: p.mod mod: p.mod
name: p.tok.lit name: p.tok.lit

View File

@ -3,11 +3,10 @@
// that can be found in the LICENSE file. // that can be found in the LICENSE file.
module parser module parser
import v.table
import v.util
import v.ast import v.ast
import v.util
pub fn (mut p Parser) parse_array_type() table.Type { pub fn (mut p Parser) parse_array_type() ast.Type {
p.check(.lsbr) p.check(.lsbr)
// fixed array // fixed array
if p.tok.kind in [.number, .name] { if p.tok.kind in [.number, .name] {
@ -44,7 +43,7 @@ pub fn (mut p Parser) parse_array_type() table.Type {
} }
// sym := p.table.get_type_symbol(elem_type) // sym := p.table.get_type_symbol(elem_type)
idx := p.table.find_or_register_array_fixed(elem_type, fixed_size) idx := p.table.find_or_register_array_fixed(elem_type, fixed_size)
return table.new_type(idx) return ast.new_type(idx)
} }
// array // array
p.check(.rsbr) p.check(.rsbr)
@ -62,13 +61,13 @@ pub fn (mut p Parser) parse_array_type() table.Type {
nr_dims++ nr_dims++
} }
idx := p.table.find_or_register_array_with_dims(elem_type, nr_dims) idx := p.table.find_or_register_array_with_dims(elem_type, nr_dims)
return table.new_type(idx) return ast.new_type(idx)
} }
pub fn (mut p Parser) parse_map_type() table.Type { pub fn (mut p Parser) parse_map_type() ast.Type {
p.next() p.next()
if p.tok.kind != .lsbr { if p.tok.kind != .lsbr {
return table.map_type return ast.map_type
} }
p.check(.lsbr) p.check(.lsbr)
key_type := p.parse_type() key_type := p.parse_type()
@ -78,12 +77,12 @@ pub fn (mut p Parser) parse_map_type() table.Type {
// error is reported in parse_type // error is reported in parse_type
return 0 return 0
} }
if is_alias && !(key_type in [table.string_type_idx, table.voidptr_type_idx] if is_alias && !(key_type in [ast.string_type_idx, ast.voidptr_type_idx]
|| ((key_type.is_int() || key_type.is_float()) && !key_type.is_ptr())) { || ((key_type.is_int() || key_type.is_float()) && !key_type.is_ptr())) {
p.error('cannot use the alias type as the parent type is unsupported') p.error('cannot use the alias type as the parent type is unsupported')
return 0 return 0
} }
if !(key_type in [table.string_type_idx, table.voidptr_type_idx] if !(key_type in [ast.string_type_idx, ast.voidptr_type_idx]
|| key_sym.kind == .enum_ || ((key_type.is_int() || key_type.is_float() || key_sym.kind == .enum_ || ((key_type.is_int() || key_type.is_float()
|| is_alias) && !key_type.is_ptr())) { || is_alias) && !key_type.is_ptr())) {
s := p.table.type_to_str(key_type) s := p.table.type_to_str(key_type)
@ -97,29 +96,29 @@ pub fn (mut p Parser) parse_map_type() table.Type {
// error is reported in parse_type // error is reported in parse_type
return 0 return 0
} }
if value_type.idx() == table.void_type_idx { if value_type.idx() == ast.void_type_idx {
p.error_with_pos('map value type cannot be void', p.tok.position()) p.error_with_pos('map value type cannot be void', p.tok.position())
return 0 return 0
} }
idx := p.table.find_or_register_map(key_type, value_type) idx := p.table.find_or_register_map(key_type, value_type)
return table.new_type(idx) return ast.new_type(idx)
} }
pub fn (mut p Parser) parse_chan_type() table.Type { pub fn (mut p Parser) parse_chan_type() ast.Type {
if p.peek_tok.kind != .name && p.peek_tok.kind != .key_mut && p.peek_tok.kind != .amp if p.peek_tok.kind != .name && p.peek_tok.kind != .key_mut && p.peek_tok.kind != .amp
&& p.peek_tok.kind != .lsbr { && p.peek_tok.kind != .lsbr {
p.next() p.next()
return table.chan_type return ast.chan_type
} }
p.register_auto_import('sync') p.register_auto_import('sync')
p.next() p.next()
is_mut := p.tok.kind == .key_mut is_mut := p.tok.kind == .key_mut
elem_type := p.parse_type() elem_type := p.parse_type()
idx := p.table.find_or_register_chan(elem_type, is_mut) idx := p.table.find_or_register_chan(elem_type, is_mut)
return table.new_type(idx) return ast.new_type(idx)
} }
pub fn (mut p Parser) parse_thread_type() table.Type { pub fn (mut p Parser) parse_thread_type() ast.Type {
is_opt := p.peek_tok.kind == .question is_opt := p.peek_tok.kind == .question
if is_opt { if is_opt {
p.next() p.next()
@ -128,12 +127,12 @@ pub fn (mut p Parser) parse_thread_type() table.Type {
&& p.peek_tok.kind != .lsbr { && p.peek_tok.kind != .lsbr {
p.next() p.next()
if is_opt { if is_opt {
mut ret_type := table.void_type mut ret_type := ast.void_type
ret_type = ret_type.set_flag(.optional) ret_type = ret_type.set_flag(.optional)
idx := p.table.find_or_register_thread(ret_type) idx := p.table.find_or_register_thread(ret_type)
return table.new_type(idx) return ast.new_type(idx)
} else { } else {
return table.thread_type return ast.thread_type
} }
} }
if !is_opt { if !is_opt {
@ -141,12 +140,12 @@ pub fn (mut p Parser) parse_thread_type() table.Type {
} }
ret_type := p.parse_type() ret_type := p.parse_type()
idx := p.table.find_or_register_thread(ret_type) idx := p.table.find_or_register_thread(ret_type)
return table.new_type(idx) return ast.new_type(idx)
} }
pub fn (mut p Parser) parse_multi_return_type() table.Type { pub fn (mut p Parser) parse_multi_return_type() ast.Type {
p.check(.lpar) p.check(.lpar)
mut mr_types := []table.Type{} mut mr_types := []ast.Type{}
for p.tok.kind != .eof { for p.tok.kind != .eof {
mr_type := p.parse_type() mr_type := p.parse_type()
if mr_type.idx() == 0 { if mr_type.idx() == 0 {
@ -165,20 +164,20 @@ pub fn (mut p Parser) parse_multi_return_type() table.Type {
return mr_types[0] return mr_types[0]
} }
idx := p.table.find_or_register_multi_return(mr_types) idx := p.table.find_or_register_multi_return(mr_types)
return table.new_type(idx) return ast.new_type(idx)
} }
// given anon name based off signature when `name` is blank // given anon name based off signature when `name` is blank
pub fn (mut p Parser) parse_fn_type(name string) table.Type { pub fn (mut p Parser) parse_fn_type(name string) ast.Type {
// p.warn('parse fn') // p.warn('parse fn')
p.check(.key_fn) p.check(.key_fn)
line_nr := p.tok.line_nr line_nr := p.tok.line_nr
args, _, is_variadic := p.fn_args() args, _, is_variadic := p.fn_args()
mut return_type := table.void_type mut return_type := ast.void_type
if p.tok.line_nr == line_nr && p.tok.kind.is_start_of_type() { if p.tok.line_nr == line_nr && p.tok.kind.is_start_of_type() {
return_type = p.parse_type() return_type = p.parse_type()
} }
func := table.Fn{ func := ast.Fn{
name: name name: name
params: args params: args
is_variadic: is_variadic is_variadic: is_variadic
@ -188,10 +187,10 @@ pub fn (mut p Parser) parse_fn_type(name string) table.Type {
// because typedefs get generated after the map struct is generated // because typedefs get generated after the map struct is generated
has_decl := p.builtin_mod && name.starts_with('Map') && name.ends_with('Fn') has_decl := p.builtin_mod && name.starts_with('Map') && name.ends_with('Fn')
idx := p.table.find_or_register_fn_type(p.mod, func, false, has_decl) idx := p.table.find_or_register_fn_type(p.mod, func, false, has_decl)
return table.new_type(idx) return ast.new_type(idx)
} }
pub fn (mut p Parser) parse_type_with_mut(is_mut bool) table.Type { pub fn (mut p Parser) parse_type_with_mut(is_mut bool) ast.Type {
typ := p.parse_type() typ := p.parse_type()
if is_mut { if is_mut {
return typ.set_nr_muls(1) return typ.set_nr_muls(1)
@ -200,13 +199,13 @@ pub fn (mut p Parser) parse_type_with_mut(is_mut bool) table.Type {
} }
// Parses any language indicators on a type. // Parses any language indicators on a type.
pub fn (mut p Parser) parse_language() table.Language { pub fn (mut p Parser) parse_language() ast.Language {
language := if p.tok.lit == 'C' { language := if p.tok.lit == 'C' {
table.Language.c ast.Language.c
} else if p.tok.lit == 'JS' { } else if p.tok.lit == 'JS' {
table.Language.js ast.Language.js
} else { } else {
table.Language.v ast.Language.v
} }
if language != .v { if language != .v {
p.next() p.next()
@ -215,7 +214,7 @@ pub fn (mut p Parser) parse_language() table.Language {
return language return language
} }
pub fn (mut p Parser) parse_type() table.Type { pub fn (mut p Parser) parse_type() ast.Type {
// optional // optional
mut is_optional := false mut is_optional := false
if p.tok.kind == .question { if p.tok.kind == .question {
@ -223,7 +222,7 @@ pub fn (mut p Parser) parse_type() table.Type {
p.next() p.next()
is_optional = true is_optional = true
if p.tok.line_nr > line_nr { if p.tok.line_nr > line_nr {
mut typ := table.void_type mut typ := ast.void_type
if is_optional { if is_optional {
typ = typ.set_flag(.optional) typ = typ.set_flag(.optional)
} }
@ -252,7 +251,7 @@ pub fn (mut p Parser) parse_type() table.Type {
p.next() p.next()
} }
language := p.parse_language() language := p.parse_language()
mut typ := table.void_type mut typ := ast.void_type
is_array := p.tok.kind == .lsbr is_array := p.tok.kind == .lsbr
if p.tok.kind != .lcbr { if p.tok.kind != .lcbr {
pos := p.tok.position() pos := p.tok.position()
@ -261,7 +260,7 @@ pub fn (mut p Parser) parse_type() table.Type {
// error is set in parse_type // error is set in parse_type
return 0 return 0
} }
if typ == table.void_type { if typ == ast.void_type {
p.error_with_pos('use `?` instead of `?void`', pos) p.error_with_pos('use `?` instead of `?void`', pos)
return 0 return 0
} }
@ -287,7 +286,7 @@ If you need to modify an array in a function, use a mutable argument instead: `f
return typ return typ
} }
pub fn (mut p Parser) parse_any_type(language table.Language, is_ptr bool, check_dot bool) table.Type { pub fn (mut p Parser) parse_any_type(language ast.Language, is_ptr bool, check_dot bool) ast.Type {
mut name := p.tok.lit mut name := p.tok.lit
if language == .c { if language == .c {
name = 'C.$name' name = 'C.$name'
@ -358,58 +357,58 @@ pub fn (mut p Parser) parse_any_type(language table.Language, is_ptr bool, check
} }
match name { match name {
'voidptr' { 'voidptr' {
return table.voidptr_type return ast.voidptr_type
} }
'byteptr' { 'byteptr' {
return table.byteptr_type return ast.byteptr_type
} }
'charptr' { 'charptr' {
return table.charptr_type return ast.charptr_type
} }
'i8' { 'i8' {
return table.i8_type return ast.i8_type
} }
'i16' { 'i16' {
return table.i16_type return ast.i16_type
} }
'int' { 'int' {
return table.int_type return ast.int_type
} }
'i64' { 'i64' {
return table.i64_type return ast.i64_type
} }
'byte' { 'byte' {
return table.byte_type return ast.byte_type
} }
'u16' { 'u16' {
return table.u16_type return ast.u16_type
} }
'u32' { 'u32' {
return table.u32_type return ast.u32_type
} }
'u64' { 'u64' {
return table.u64_type return ast.u64_type
} }
'f32' { 'f32' {
return table.f32_type return ast.f32_type
} }
'f64' { 'f64' {
return table.f64_type return ast.f64_type
} }
'string' { 'string' {
return table.string_type return ast.string_type
} }
'char' { 'char' {
return table.char_type return ast.char_type
} }
'bool' { 'bool' {
return table.bool_type return ast.bool_type
} }
'float_literal' { 'float_literal' {
return table.float_literal_type return ast.float_literal_type
} }
'int_literal' { 'int_literal' {
return table.int_literal_type return ast.int_literal_type
} }
else { else {
if name.len == 1 && name[0].is_capital() { if name.len == 1 && name[0].is_capital() {
@ -425,42 +424,42 @@ pub fn (mut p Parser) parse_any_type(language table.Language, is_ptr bool, check
} }
} }
pub fn (mut p Parser) parse_enum_or_struct_type(name string, language table.Language) table.Type { pub fn (mut p Parser) parse_enum_or_struct_type(name string, language ast.Language) ast.Type {
// struct / enum / placeholder // struct / enum / placeholder
// struct / enum // struct / enum
mut idx := p.table.find_type_idx(name) mut idx := p.table.find_type_idx(name)
if idx > 0 { if idx > 0 {
return table.new_type(idx) return ast.new_type(idx)
} }
// not found - add placeholder // not found - add placeholder
idx = p.table.add_placeholder_type(name, language) idx = p.table.add_placeholder_type(name, language)
// println('NOT FOUND: $name - adding placeholder - $idx') // println('NOT FOUND: $name - adding placeholder - $idx')
return table.new_type(idx) return ast.new_type(idx)
} }
pub fn (mut p Parser) parse_generic_template_type(name string) table.Type { pub fn (mut p Parser) parse_generic_template_type(name string) ast.Type {
mut idx := p.table.find_type_idx(name) mut idx := p.table.find_type_idx(name)
if idx > 0 { if idx > 0 {
return table.new_type(idx).set_flag(.generic) return ast.new_type(idx).set_flag(.generic)
} }
idx = p.table.register_type_symbol(table.TypeSymbol{ idx = p.table.register_type_symbol(ast.TypeSymbol{
name: name name: name
cname: util.no_dots(name) cname: util.no_dots(name)
mod: p.mod mod: p.mod
kind: .any kind: .any
is_public: true is_public: true
}) })
return table.new_type(idx).set_flag(.generic) return ast.new_type(idx).set_flag(.generic)
} }
pub fn (mut p Parser) parse_generic_struct_inst_type(name string) table.Type { pub fn (mut p Parser) parse_generic_struct_inst_type(name string) ast.Type {
mut bs_name := name mut bs_name := name
mut bs_cname := name mut bs_cname := name
p.next() p.next()
p.in_generic_params = true p.in_generic_params = true
bs_name += '<' bs_name += '<'
bs_cname += '_T_' bs_cname += '_T_'
mut generic_types := []table.Type{} mut generic_types := []ast.Type{}
mut is_instance := false mut is_instance := false
for p.tok.kind != .eof { for p.tok.kind != .eof {
gt := p.parse_type() gt := p.parse_type()
@ -484,28 +483,28 @@ pub fn (mut p Parser) parse_generic_struct_inst_type(name string) table.Type {
if is_instance && generic_types.len > 0 { if is_instance && generic_types.len > 0 {
mut gt_idx := p.table.find_type_idx(bs_name) mut gt_idx := p.table.find_type_idx(bs_name)
if gt_idx > 0 { if gt_idx > 0 {
return table.new_type(gt_idx) return ast.new_type(gt_idx)
} }
gt_idx = p.table.add_placeholder_type(bs_name, .v) gt_idx = p.table.add_placeholder_type(bs_name, .v)
mut parent_idx := p.table.type_idxs[name] mut parent_idx := p.table.type_idxs[name]
if parent_idx == 0 { if parent_idx == 0 {
parent_idx = p.table.add_placeholder_type(name, .v) parent_idx = p.table.add_placeholder_type(name, .v)
} }
idx := p.table.register_type_symbol(table.TypeSymbol{ idx := p.table.register_type_symbol(ast.TypeSymbol{
kind: .generic_struct_inst kind: .generic_struct_inst
name: bs_name name: bs_name
cname: util.no_dots(bs_cname) cname: util.no_dots(bs_cname)
mod: p.mod mod: p.mod
info: table.GenericStructInst{ info: ast.GenericStructInst{
parent_idx: parent_idx parent_idx: parent_idx
generic_types: generic_types generic_types: generic_types
} }
}) })
return table.new_type(idx) return ast.new_type(idx)
} else { } else {
idx := p.table.find_type_idx(name) idx := p.table.find_type_idx(name)
if idx != 0 { if idx != 0 {
return table.new_type(idx).set_flag(.generic) return ast.new_type(idx).set_flag(.generic)
} }
} }
return p.parse_enum_or_struct_type(name, .v) return p.parse_enum_or_struct_type(name, .v)

View File

@ -6,7 +6,6 @@ module parser
import v.scanner import v.scanner
import v.ast import v.ast
import v.token import v.token
import v.table
import v.pref import v.pref
import v.util import v.util
import v.vet import v.vet
@ -20,18 +19,18 @@ const (
pub struct Parser { pub struct Parser {
pref &pref.Preferences pref &pref.Preferences
mut: mut:
file_base string // "hello.v" file_base string // "hello.v"
file_name string // "/home/user/hello.v" file_name string // "/home/user/hello.v"
file_name_dir string // "/home/user" file_name_dir string // "/home/user"
file_backend_mode table.Language // .c for .c.v|.c.vv|.c.vsh files; .js for .js.v files, .amd64/.rv32/other arches for .amd64.v/.rv32.v/etc. files, .v otherwise. file_backend_mode ast.Language // .c for .c.v|.c.vv|.c.vsh files; .js for .js.v files, .amd64/.rv32/other arches for .amd64.v/.rv32.v/etc. files, .v otherwise.
scanner &scanner.Scanner scanner &scanner.Scanner
comments_mode scanner.CommentsMode = .skip_comments comments_mode scanner.CommentsMode = .skip_comments
// see comment in parse_file // see comment in parse_file
tok token.Token tok token.Token
prev_tok token.Token prev_tok token.Token
peek_tok token.Token peek_tok token.Token
table &table.Table table &ast.Table
language table.Language language ast.Language
inside_if bool inside_if bool
inside_if_expr bool inside_if_expr bool
inside_ct_if_expr bool inside_ct_if_expr bool
@ -40,12 +39,12 @@ mut:
inside_fn bool // true even with implicit main inside_fn bool // true even with implicit main
inside_unsafe_fn bool inside_unsafe_fn bool
inside_str_interp bool inside_str_interp bool
or_is_handled bool // ignore `or` in this expression or_is_handled bool // ignore `or` in this expression
builtin_mod bool // are we in the `builtin` module? builtin_mod bool // are we in the `builtin` module?
mod string // current module name mod string // current module name
is_manualfree bool // true when `[manualfree] module abc`, makes *all* fns in the current .v file, opt out of autofree is_manualfree bool // true when `[manualfree] module abc`, makes *all* fns in the current .v file, opt out of autofree
attrs []table.Attr // attributes before next decl stmt attrs []ast.Attr // attributes before next decl stmt
expr_mod string // for constructing full type names in parse_type() expr_mod string // for constructing full type names in parse_type()
scope &ast.Scope scope &ast.Scope
global_scope &ast.Scope global_scope &ast.Scope
imports map[string]string // alias => mod_name imports map[string]string // alias => mod_name
@ -77,7 +76,7 @@ mut:
} }
// for tests // for tests
pub fn parse_stmt(text string, table &table.Table, scope &ast.Scope) ast.Stmt { pub fn parse_stmt(text string, table &ast.Table, scope &ast.Scope) ast.Stmt {
mut p := Parser{ mut p := Parser{
scanner: scanner.new_scanner(text, .skip_comments, &pref.Preferences{}) scanner: scanner.new_scanner(text, .skip_comments, &pref.Preferences{})
table: table table: table
@ -97,7 +96,7 @@ pub fn parse_stmt(text string, table &table.Table, scope &ast.Scope) ast.Stmt {
return p.stmt(false) return p.stmt(false)
} }
pub fn parse_comptime(text string, table &table.Table, pref &pref.Preferences, scope &ast.Scope, global_scope &ast.Scope) ast.File { pub fn parse_comptime(text string, table &ast.Table, pref &pref.Preferences, scope &ast.Scope, global_scope &ast.Scope) ast.File {
mut p := Parser{ mut p := Parser{
scanner: scanner.new_scanner(text, .skip_comments, pref) scanner: scanner.new_scanner(text, .skip_comments, pref)
table: table table: table
@ -110,7 +109,7 @@ pub fn parse_comptime(text string, table &table.Table, pref &pref.Preferences, s
return p.parse() return p.parse()
} }
pub fn parse_text(text string, path string, table &table.Table, comments_mode scanner.CommentsMode, pref &pref.Preferences, global_scope &ast.Scope) ast.File { pub fn parse_text(text string, path string, table &ast.Table, comments_mode scanner.CommentsMode, pref &pref.Preferences, global_scope &ast.Scope) ast.File {
mut p := Parser{ mut p := Parser{
scanner: scanner.new_scanner(text, comments_mode, pref) scanner: scanner.new_scanner(text, comments_mode, pref)
comments_mode: comments_mode comments_mode: comments_mode
@ -156,7 +155,7 @@ pub fn (mut p Parser) set_path(path string) {
} }
else { else {
arch := pref.arch_from_string(actual_language) or { pref.Arch._auto } arch := pref.arch_from_string(actual_language) or { pref.Arch._auto }
p.file_backend_mode = table.pref_arch_to_table_language(arch) p.file_backend_mode = ast.pref_arch_to_table_language(arch)
if arch == ._auto { if arch == ._auto {
p.file_backend_mode = .v p.file_backend_mode = .v
} }
@ -164,7 +163,7 @@ pub fn (mut p Parser) set_path(path string) {
} }
} }
pub fn parse_file(path string, table &table.Table, comments_mode scanner.CommentsMode, pref &pref.Preferences, global_scope &ast.Scope) ast.File { pub fn parse_file(path string, table &ast.Table, comments_mode scanner.CommentsMode, pref &pref.Preferences, global_scope &ast.Scope) ast.File {
// NB: when comments_mode == .toplevel_comments, // NB: when comments_mode == .toplevel_comments,
// the parser gives feedback to the scanner about toplevel statements, so that the scanner can skip // the parser gives feedback to the scanner about toplevel statements, so that the scanner can skip
// all the tricky inner comments. This is needed because we do not have a good general solution // all the tricky inner comments. This is needed because we do not have a good general solution
@ -190,7 +189,7 @@ pub fn parse_file(path string, table &table.Table, comments_mode scanner.Comment
return p.parse() return p.parse()
} }
pub fn parse_vet_file(path string, table_ &table.Table, pref &pref.Preferences) (ast.File, []vet.Error) { pub fn parse_vet_file(path string, table_ &ast.Table, pref &pref.Preferences) (ast.File, []vet.Error) {
global_scope := &ast.Scope{ global_scope := &ast.Scope{
parent: 0 parent: 0
} }
@ -293,7 +292,7 @@ mut:
mu &sync.Mutex mu &sync.Mutex
mu2 &sync.Mutex mu2 &sync.Mutex
paths []string paths []string
table &table.Table table &ast.Table
parsed_ast_files []ast.File parsed_ast_files []ast.File
pref &pref.Preferences pref &pref.Preferences
global_scope &ast.Scope global_scope &ast.Scope
@ -319,7 +318,7 @@ fn (mut q Queue) run() {
} }
} }
*/ */
pub fn parse_files(paths []string, table &table.Table, pref &pref.Preferences, global_scope &ast.Scope) []ast.File { pub fn parse_files(paths []string, table &ast.Table, pref &pref.Preferences, global_scope &ast.Scope) []ast.File {
mut timers := util.new_timers(false) mut timers := util.new_timers(false)
$if time_parsing ? { $if time_parsing ? {
timers.should_print = true timers.should_print = true
@ -585,7 +584,7 @@ pub fn (mut p Parser) top_stmt() ast.Stmt {
is_main: true is_main: true
stmts: stmts stmts: stmts
file: p.file_name file: p.file_name
return_type: table.void_type return_type: ast.void_type
scope: p.scope scope: p.scope
label_names: p.label_names label_names: p.label_names
} }
@ -867,7 +866,7 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt {
p.check(.name) p.check(.name)
} }
p.check_for_impure_v(table.pref_arch_to_table_language(arch), p.prev_tok.position()) p.check_for_impure_v(ast.pref_arch_to_table_language(arch), p.prev_tok.position())
p.check(.lcbr) p.check(.lcbr)
p.scope = &ast.Scope{ p.scope = &ast.Scope{
@ -1454,11 +1453,11 @@ fn (mut p Parser) attributes() {
} }
} }
fn (mut p Parser) parse_attr() table.Attr { fn (mut p Parser) parse_attr() ast.Attr {
apos := p.prev_tok.position() apos := p.prev_tok.position()
if p.tok.kind == .key_unsafe { if p.tok.kind == .key_unsafe {
p.next() p.next()
return table.Attr{ return ast.Attr{
name: 'unsafe' name: 'unsafe'
pos: apos.extend(p.tok.position()) pos: apos.extend(p.tok.position())
} }
@ -1478,10 +1477,10 @@ fn (mut p Parser) parse_attr() table.Attr {
name = p.check_name() name = p.check_name()
if name == 'unsafe_fn' { if name == 'unsafe_fn' {
p.error_with_pos('[unsafe_fn] is obsolete, use `[unsafe]` instead', apos.extend(p.tok.position())) p.error_with_pos('[unsafe_fn] is obsolete, use `[unsafe]` instead', apos.extend(p.tok.position()))
return table.Attr{} return ast.Attr{}
} else if name == 'trusted_fn' { } else if name == 'trusted_fn' {
p.error_with_pos('[trusted_fn] is obsolete, use `[trusted]` instead', apos.extend(p.tok.position())) p.error_with_pos('[trusted_fn] is obsolete, use `[trusted]` instead', apos.extend(p.tok.position()))
return table.Attr{} return ast.Attr{}
} else if name == 'ref_only' { } else if name == 'ref_only' {
p.warn_with_pos('[ref_only] is deprecated, use [heap] instead', apos.extend(p.tok.position())) p.warn_with_pos('[ref_only] is deprecated, use [heap] instead', apos.extend(p.tok.position()))
name = 'heap' name = 'heap'
@ -1498,7 +1497,7 @@ fn (mut p Parser) parse_attr() table.Attr {
} }
} }
} }
return table.Attr{ return ast.Attr{
name: name name: name
is_string: is_string is_string: is_string
is_comptime_define: is_comptime_define is_comptime_define: is_comptime_define
@ -1508,7 +1507,7 @@ fn (mut p Parser) parse_attr() table.Attr {
} }
} }
pub fn (mut p Parser) check_for_impure_v(language table.Language, pos token.Position) { pub fn (mut p Parser) check_for_impure_v(language ast.Language, pos token.Position) {
if language == .v { if language == .v {
// pure V code is always allowed everywhere // pure V code is always allowed everywhere
return return
@ -1698,7 +1697,7 @@ fn (mut p Parser) parse_multi_expr(is_top_level bool) ast.Stmt {
} }
} }
pub fn (mut p Parser) parse_ident(language table.Language) ast.Ident { pub fn (mut p Parser) parse_ident(language ast.Language) ast.Ident {
// p.warn('name ') // p.warn('name ')
is_shared := p.tok.kind == .key_shared is_shared := p.tok.kind == .key_shared
is_atomic := p.tok.kind == .key_atomic is_atomic := p.tok.kind == .key_atomic
@ -1748,7 +1747,7 @@ pub fn (mut p Parser) parse_ident(language table.Language) ast.Ident {
info: ast.IdentVar{ info: ast.IdentVar{
is_mut: is_mut is_mut: is_mut
is_static: is_static is_static: is_static
share: table.sharetype_from_flags(is_shared, is_atomic) share: ast.sharetype_from_flags(is_shared, is_atomic)
} }
scope: p.scope scope: p.scope
} }
@ -1817,17 +1816,17 @@ pub fn (mut p Parser) name_expr() ast.Expr {
// get type position before moving to next // get type position before moving to next
type_pos := p.tok.position() type_pos := p.tok.position()
typ := p.parse_type() typ := p.parse_type()
return ast.Type{ return ast.TypeNode{
typ: typ typ: typ
pos: type_pos pos: type_pos
} }
} }
mut language := table.Language.v mut language := ast.Language.v
if p.tok.lit == 'C' { if p.tok.lit == 'C' {
language = table.Language.c language = ast.Language.c
p.check_for_impure_v(language, p.tok.position()) p.check_for_impure_v(language, p.tok.position())
} else if p.tok.lit == 'JS' { } else if p.tok.lit == 'JS' {
language = table.Language.js language = ast.Language.js
p.check_for_impure_v(language, p.tok.position()) p.check_for_impure_v(language, p.tok.position())
} }
mut mod := '' mut mod := ''
@ -1947,7 +1946,7 @@ pub fn (mut p Parser) name_expr() ast.Expr {
} }
name_w_mod := p.prepend_mod(name) name_w_mod := p.prepend_mod(name)
// type cast. TODO: finish // type cast. TODO: finish
// if name in table.builtin_type_names { // if name in ast.builtin_type_names {
if (!known_var && (name in p.table.type_idxs || name_w_mod in p.table.type_idxs) if (!known_var && (name in p.table.type_idxs || name_w_mod in p.table.type_idxs)
&& name !in ['C.stat', 'C.sigaction']) || is_mod_cast && name !in ['C.stat', 'C.sigaction']) || is_mod_cast
|| (language == .v && name[0].is_capital()) { || (language == .v && name[0].is_capital()) {
@ -1969,7 +1968,7 @@ pub fn (mut p Parser) name_expr() ast.Expr {
mut has_arg := false mut has_arg := false
expr = p.expr(0) expr = p.expr(0)
// TODO, string(b, len) // TODO, string(b, len)
if p.tok.kind == .comma && to_typ.idx() == table.string_type_idx { if p.tok.kind == .comma && to_typ.idx() == ast.string_type_idx {
p.next() p.next()
arg = p.expr(0) // len arg = p.expr(0) // len
has_arg = true has_arg = true
@ -2189,7 +2188,7 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
} }
// Method call // Method call
// TODO move to fn.v call_expr() // TODO move to fn.v call_expr()
mut generic_types := []table.Type{} mut generic_types := []ast.Type{}
mut generic_list_pos := p.tok.position() mut generic_list_pos := p.tok.position()
if is_generic_call { if is_generic_call {
// `g.foo<int>(10)` // `g.foo<int>(10)`
@ -2215,7 +2214,7 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
p.open_scope() p.open_scope()
p.scope.register(ast.Var{ p.scope.register(ast.Var{
name: 'err' name: 'err'
typ: table.error_type typ: ast.error_type
pos: p.tok.position() pos: p.tok.position()
is_used: true is_used: true
}) })
@ -2281,8 +2280,8 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
return sel_expr return sel_expr
} }
fn (mut p Parser) parse_generic_type_list() []table.Type { fn (mut p Parser) parse_generic_type_list() []ast.Type {
mut types := []table.Type{} mut types := []ast.Type{}
if p.tok.kind != .lt { if p.tok.kind != .lt {
return types return types
} }
@ -2325,7 +2324,7 @@ fn (mut p Parser) string_expr() ast.Expr {
node = ast.StringLiteral{ node = ast.StringLiteral{
val: val val: val
is_raw: is_raw is_raw: is_raw
language: if is_cstr { table.Language.c } else { table.Language.v } language: if is_cstr { ast.Language.c } else { ast.Language.v }
pos: pos pos: pos
} }
return node return node
@ -2443,7 +2442,7 @@ fn (mut p Parser) parse_number_literal() ast.Expr {
} }
fn (mut p Parser) module_decl() ast.Module { fn (mut p Parser) module_decl() ast.Module {
mut module_attrs := []table.Attr{} mut module_attrs := []ast.Attr{}
mut attrs_pos := p.tok.position() mut attrs_pos := p.tok.position()
if p.tok.kind == .lsbr { if p.tok.kind == .lsbr {
p.attributes() p.attributes()
@ -2874,12 +2873,12 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
// //
') ')
} }
idx := p.table.register_type_symbol(table.TypeSymbol{ idx := p.table.register_type_symbol(ast.TypeSymbol{
kind: .enum_ kind: .enum_
name: name name: name
cname: util.no_dots(name) cname: util.no_dots(name)
mod: p.mod mod: p.mod
info: table.Enum{ info: ast.Enum{
vals: vals vals: vals
is_flag: is_flag is_flag: is_flag
is_multi_allowed: is_multi_allowed is_multi_allowed: is_multi_allowed
@ -2963,12 +2962,12 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
} }
variant_types := sum_variants.map(it.typ) variant_types := sum_variants.map(it.typ)
prepend_mod_name := p.prepend_mod(name) prepend_mod_name := p.prepend_mod(name)
typ := p.table.register_type_symbol(table.TypeSymbol{ typ := p.table.register_type_symbol(ast.TypeSymbol{
kind: .sum_type kind: .sum_type
name: prepend_mod_name name: prepend_mod_name
cname: util.no_dots(prepend_mod_name) cname: util.no_dots(prepend_mod_name)
mod: p.mod mod: p.mod
info: table.SumType{ info: ast.SumType{
variants: variant_types variants: variant_types
} }
is_public: is_pub is_public: is_pub
@ -2989,13 +2988,13 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
pidx := parent_type.idx() pidx := parent_type.idx()
p.check_for_impure_v(parent_sym.language, decl_pos) p.check_for_impure_v(parent_sym.language, decl_pos)
prepend_mod_name := p.prepend_mod(name) prepend_mod_name := p.prepend_mod(name)
idx := p.table.register_type_symbol(table.TypeSymbol{ idx := p.table.register_type_symbol(ast.TypeSymbol{
kind: .alias kind: .alias
name: prepend_mod_name name: prepend_mod_name
cname: util.no_dots(prepend_mod_name) cname: util.no_dots(prepend_mod_name)
mod: p.mod mod: p.mod
parent_idx: pidx parent_idx: pidx
info: table.Alias{ info: ast.Alias{
parent_type: parent_type parent_type: parent_type
language: parent_sym.language language: parent_sym.language
} }

View File

@ -5,7 +5,6 @@ module parser
import v.ast import v.ast
import v.vet import v.vet
import v.table
import v.token import v.token
pub fn (mut p Parser) expr(precedence int) ast.Expr { pub fn (mut p Parser) expr(precedence int) ast.Expr {
@ -23,7 +22,7 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
// Prefix // Prefix
match p.tok.kind { match p.tok.kind {
.key_mut, .key_shared, .key_atomic, .key_static { .key_mut, .key_shared, .key_atomic, .key_static {
node = p.parse_ident(table.Language.v) node = p.parse_ident(ast.Language.v)
p.is_stmt_ident = is_stmt_ident p.is_stmt_ident = is_stmt_ident
} }
.name { .name {
@ -292,7 +291,7 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
if p.expecting_type { if p.expecting_type {
// Anonymous function type // Anonymous function type
start_pos := p.tok.position() start_pos := p.tok.position()
return ast.Type{ return ast.TypeNode{
typ: p.parse_type() typ: p.parse_type()
pos: start_pos.extend(p.prev_tok.position()) pos: start_pos.extend(p.prev_tok.position())
} }
@ -460,7 +459,7 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr {
p.open_scope() p.open_scope()
p.scope.register(ast.Var{ p.scope.register(ast.Var{
name: 'err' name: 'err'
typ: table.error_type typ: ast.error_type
pos: p.tok.position() pos: p.tok.position()
is_used: true is_used: true
}) })
@ -523,7 +522,7 @@ fn (mut p Parser) prefix_expr() ast.PrefixExpr {
p.open_scope() p.open_scope()
p.scope.register(ast.Var{ p.scope.register(ast.Var{
name: 'err' name: 'err'
typ: table.error_type typ: ast.error_type
pos: p.tok.position() pos: p.tok.position()
is_used: true is_used: true
}) })

View File

@ -4,7 +4,6 @@
module parser module parser
import v.ast import v.ast
import v.table
fn (mut p Parser) sql_expr() ast.Expr { fn (mut p Parser) sql_expr() ast.Expr {
// `sql db {` // `sql db {`
@ -15,10 +14,10 @@ fn (mut p Parser) sql_expr() ast.Expr {
p.check(.key_select) p.check(.key_select)
n := p.check_name() n := p.check_name()
is_count := n == 'count' is_count := n == 'count'
mut typ := table.void_type mut typ := ast.void_type
if is_count { if is_count {
p.check_name() // from p.check_name() // from
typ = table.int_type typ = ast.int_type
} }
table_pos := p.tok.position() table_pos := p.tok.position()
table_type := p.parse_type() // `User` table_type := p.parse_type() // `User`
@ -77,7 +76,7 @@ fn (mut p Parser) sql_expr() ast.Expr {
} }
if !query_one && !is_count { if !query_one && !is_count {
// return an array // return an array
typ = table.new_type(p.table.find_or_register_array(table_type)) typ = ast.new_type(p.table.find_or_register_array(table_type))
} else if !is_count { } else if !is_count {
// return a single object // return a single object
// TODO optional // TODO optional
@ -100,7 +99,7 @@ fn (mut p Parser) sql_expr() ast.Expr {
has_desc: has_desc has_desc: has_desc
is_array: !query_one is_array: !query_one
pos: pos.extend(p.prev_tok.position()) pos: pos.extend(p.prev_tok.position())
table_expr: ast.Type{ table_expr: ast.TypeNode{
typ: table_type typ: table_type
pos: table_pos pos: table_pos
} }
@ -130,7 +129,7 @@ fn (mut p Parser) sql_stmt() ast.SqlStmt {
kind = .update kind = .update
} }
mut inserted_var_name := '' mut inserted_var_name := ''
mut table_type := table.Type(0) mut table_type := ast.Type(0)
if kind != .delete { if kind != .delete {
if kind == .update { if kind == .update {
table_type = p.parse_type() table_type = p.parse_type()
@ -189,7 +188,7 @@ fn (mut p Parser) sql_stmt() ast.SqlStmt {
pos.last_line = p.prev_tok.line_nr pos.last_line = p.prev_tok.line_nr
return ast.SqlStmt{ return ast.SqlStmt{
db_expr: db_expr db_expr: db_expr
table_expr: ast.Type{ table_expr: ast.TypeNode{
typ: table_type typ: table_type
pos: table_pos pos: table_pos
} }

View File

@ -4,7 +4,6 @@
module parser module parser
import v.ast import v.ast
import v.table
import v.token import v.token
import v.util import v.util
@ -25,11 +24,11 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
p.check(.key_union) p.check(.key_union)
} }
language := if p.tok.lit == 'C' && p.peek_tok.kind == .dot { language := if p.tok.lit == 'C' && p.peek_tok.kind == .dot {
table.Language.c ast.Language.c
} else if p.tok.lit == 'JS' && p.peek_tok.kind == .dot { } else if p.tok.lit == 'JS' && p.peek_tok.kind == .dot {
table.Language.js ast.Language.js
} else { } else {
table.Language.v ast.Language.v
} }
if language != .v { if language != .v {
p.next() // C || JS p.next() // C || JS
@ -48,7 +47,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
name_pos) name_pos)
return ast.StructDecl{} return ast.StructDecl{}
} }
mut generic_types := []table.Type{} mut generic_types := []ast.Type{}
if p.tok.kind == .lt { if p.tok.kind == .lt {
p.next() p.next()
for { for {
@ -85,8 +84,8 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
name = p.prepend_mod(name) name = p.prepend_mod(name)
} }
mut ast_fields := []ast.StructField{} mut ast_fields := []ast.StructField{}
mut fields := []table.Field{} mut fields := []ast.StructField{}
mut embed_types := []table.Type{} mut embed_types := []ast.Type{}
mut embeds := []ast.Embed{} mut embeds := []ast.Embed{}
mut embed_field_names := []string{} mut embed_field_names := []string{}
mut mut_pos := -1 mut mut_pos := -1
@ -181,7 +180,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
|| p.peek_tok.kind == .dot) && language == .v && p.peek_tok.kind != .key_fn || p.peek_tok.kind == .dot) && language == .v && p.peek_tok.kind != .key_fn
is_on_top := ast_fields.len == 0 && !(is_field_mut || is_field_mut || is_field_global) is_on_top := ast_fields.len == 0 && !(is_field_mut || is_field_mut || is_field_global)
mut field_name := '' mut field_name := ''
mut typ := table.Type(0) mut typ := ast.Type(0)
mut type_pos := token.Position{} mut type_pos := token.Position{}
mut field_pos := token.Position{} mut field_pos := token.Position{}
if is_embed { if is_embed {
@ -254,31 +253,33 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
has_default_expr = true has_default_expr = true
comments << p.eat_comments({}) comments << p.eat_comments({})
} }
// TODO merge table and ast Fields?
ast_fields << ast.StructField{ ast_fields << ast.StructField{
name: field_name name: field_name
typ: typ
pos: field_pos pos: field_pos
type_pos: type_pos type_pos: type_pos
typ: typ
comments: comments comments: comments
default_expr: default_expr default_expr: default_expr
has_default_expr: has_default_expr has_default_expr: has_default_expr
attrs: p.attrs attrs: p.attrs
is_public: is_field_pub is_pub: is_embed || is_field_pub
is_mut: is_embed || is_field_mut
is_global: is_field_global
} }
} }
is_pub_field := is_embed || is_field_pub
is_mut_field := is_embed || is_field_mut
// save embeds as table fields too, it will be used in generation phase // save embeds as table fields too, it will be used in generation phase
fields << table.Field{ fields << ast.StructField{
name: field_name name: field_name
typ: typ typ: typ
default_expr: ast.ex2fe(default_expr) pos: field_pos
type_pos: type_pos
comments: comments
default_expr: default_expr
has_default_expr: has_default_expr has_default_expr: has_default_expr
is_pub: is_pub_field
is_mut: is_mut_field
is_global: is_field_global
attrs: p.attrs attrs: p.attrs
is_pub: is_embed || is_field_pub
is_mut: is_embed || is_field_mut
is_global: is_field_global
} }
p.attrs = [] p.attrs = []
} }
@ -286,13 +287,13 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
last_line = p.tok.line_nr last_line = p.tok.line_nr
p.check(.rcbr) p.check(.rcbr)
} }
t := table.TypeSymbol{ t := ast.TypeSymbol{
kind: .struct_ kind: .struct_
language: language language: language
name: name name: name
cname: util.no_dots(name) cname: util.no_dots(name)
mod: p.mod mod: p.mod
info: table.Struct{ info: ast.Struct{
embeds: embed_types embeds: embed_types
fields: fields fields: fields
is_typedef: attrs.contains('typedef') is_typedef: attrs.contains('typedef')
@ -338,7 +339,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
fn (mut p Parser) struct_init(short_syntax bool) ast.StructInit { fn (mut p Parser) struct_init(short_syntax bool) ast.StructInit {
first_pos := p.tok.position() first_pos := p.tok.position()
typ := if short_syntax { table.void_type } else { p.parse_type() } typ := if short_syntax { ast.void_type } else { p.parse_type() }
p.expr_mod = '' p.expr_mod = ''
// sym := p.table.get_type_symbol(typ) // sym := p.table.get_type_symbol(typ)
// p.warn('struct init typ=$sym.name') // p.warn('struct init typ=$sym.name')
@ -449,7 +450,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
name: interface_name name: interface_name
cname: util.no_dots(interface_name) cname: util.no_dots(interface_name)
mod: p.mod mod: p.mod
info: table.Interface{ info: ast.Interface{
types: [] types: []
} }
) )
@ -458,11 +459,11 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
name_pos) name_pos)
return ast.InterfaceDecl{} return ast.InterfaceDecl{}
} }
typ := table.new_type(reg_idx) typ := ast.new_type(reg_idx)
mut ts := p.table.get_type_symbol(typ) mut ts := p.table.get_type_symbol(typ)
mut info := ts.info as table.Interface mut info := ts.info as ast.Interface
// if methods were declared before, it's an error, ignore them // if methods were declared before, it's an error, ignore them
ts.methods = []table.Fn{cap: 20} ts.methods = []ast.Fn{cap: 20}
// Parse fields or methods // Parse fields or methods
mut fields := []ast.StructField{cap: 20} mut fields := []ast.StructField{cap: 20}
mut methods := []ast.FnDecl{cap: 20} mut methods := []ast.FnDecl{cap: 20}
@ -496,8 +497,8 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
return ast.InterfaceDecl{} return ast.InterfaceDecl{}
} }
// field_names << name // field_names << name
args2, _, is_variadic := p.fn_args() // TODO merge table.Param and ast.Arg to avoid this args2, _, is_variadic := p.fn_args() // TODO merge ast.Param and ast.Arg to avoid this
mut args := [table.Param{ mut args := [ast.Param{
name: 'x' name: 'x'
is_mut: is_mut is_mut: is_mut
typ: typ typ: typ
@ -509,7 +510,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
mod: p.mod mod: p.mod
params: args params: args
file: p.file_name file: p.file_name
return_type: table.void_type return_type: ast.void_type
is_variadic: is_variadic is_variadic: is_variadic
is_pub: true is_pub: true
pos: method_start_pos.extend(p.prev_tok.position()) pos: method_start_pos.extend(p.prev_tok.position())
@ -524,7 +525,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
method.next_comments = mnext_comments method.next_comments = mnext_comments
methods << method methods << method
// println('register method $name') // println('register method $name')
tmethod := table.Fn{ tmethod := ast.Fn{
name: name name: name
params: args params: args
return_type: method.return_type return_type: method.return_type
@ -553,9 +554,9 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
type_pos: type_pos type_pos: type_pos
typ: field_typ typ: field_typ
comments: comments comments: comments
is_public: true is_pub: true
} }
info.fields << table.Field{ info.fields << ast.StructField{
name: field_name name: field_name
typ: field_typ typ: field_typ
is_pub: true is_pub: true

View File

@ -3,10 +3,8 @@ module parser
// import v.eval // import v.eval
import v.ast import v.ast
import v.gen.c import v.gen.c
import v.table
import v.checker import v.checker
import v.pref import v.pref
import v.scanner
import term import term
fn test_eval() { fn test_eval() {
@ -35,7 +33,7 @@ fn test_eval() {
'20', '20',
// //
] ]
table := table.new_table() table := ast.new_table()
vpref := &pref.Preferences{} vpref := &pref.Preferences{}
mut scope := &ast.Scope{ mut scope := &ast.Scope{
start_pos: 0 start_pos: 0
@ -76,7 +74,7 @@ x := 10
5+7 5+7
8+4 8+4
' '
table := &table.Table{} table := &ast.Table{}
vpref := &pref.Preferences{} vpref := &pref.Preferences{}
gscope := &ast.Scope{ gscope := &ast.Scope{
parent: 0 parent: 0
@ -95,7 +93,7 @@ fn test_one() {
println('\n\ntest_one()') println('\n\ntest_one()')
input := ['a := 10', 'b := -a', 'c := 20'] input := ['a := 10', 'b := -a', 'c := 20']
expected := 'int a = 10;int b = -a;int c = 20;' expected := 'int a = 10;int b = -a;int c = 20;'
table := table.new_table() table := ast.new_table()
vpref := &pref.Preferences{} vpref := &pref.Preferences{}
scope := &ast.Scope{ scope := &ast.Scope{
start_pos: 0 start_pos: 0
@ -136,7 +134,7 @@ fn test_parse_expr() {
'string s = tos3("hi");', 'x = 11;', 'a += 10;', '1.2 + 3.4;', '4 + 4;', '1 + 2 * 5;', 'string s = tos3("hi");', 'x = 11;', 'a += 10;', '1.2 + 3.4;', '4 + 4;', '1 + 2 * 5;',
'-a + 1;', '2 + 2;'] '-a + 1;', '2 + 2;']
mut e := []ast.Stmt{} mut e := []ast.Stmt{}
table := table.new_table() table := ast.new_table()
vpref := &pref.Preferences{} vpref := &pref.Preferences{}
mut checker := checker.new_checker(table, vpref) mut checker := checker.new_checker(table, vpref)
scope := &ast.Scope{ scope := &ast.Scope{
@ -184,7 +182,7 @@ fn test_num_literals() {
'c := -12.', 'c := -12.',
'd := -a', 'd := -a',
] ]
table := table.new_table() table := ast.new_table()
mut scope := &ast.Scope{ mut scope := &ast.Scope{
start_pos: 0 start_pos: 0
parent: 0 parent: 0
@ -211,7 +209,7 @@ fn test_num_literals() {
} }
/* /*
table := &table.Table{} table := &ast.Table{}
for s in text_expr { for s in text_expr {
// print using str method // print using str method
x := parse_expr(s, table) x := parse_expr(s, table)

View File

@ -76,7 +76,7 @@ pub fn (mut p Preferences) fill_with_defaults() {
// executable on Windows + the precompiled V is more // executable on Windows + the precompiled V is more
// optimized. // optimized.
println('Saving the resulting V executable in `./v2`') println('Saving the resulting V executable in `./v2`')
println('Use `v -o v cmd/v` if you want to replace current ' + 'V executable.') println('Use `v -o v cmd/v` if you want to replace current ' + 'V execuast.')
p.out_name = 'v2' p.out_name = 'v2'
} }
} }

View File

@ -561,7 +561,7 @@ pub fn parse_args(known_external_commands []string, args []string) (&Preferences
must_exist(res.path) must_exist(res.path)
if !res.path.ends_with('.v') && os.is_executable(res.path) && os.is_file(res.path) if !res.path.ends_with('.v') && os.is_executable(res.path) && os.is_file(res.path)
&& os.is_file(res.path + '.v') { && os.is_file(res.path + '.v') {
eprintln('It looks like you wanted to run "${res.path}.v", so we went ahead and did that since "$res.path" is an executable.') eprintln('It looks like you wanted to run "${res.path}.v", so we went ahead and did that since "$res.path" is an execuast.')
res.path += '.v' res.path += '.v'
} }
} }

View File

@ -1,7 +1,7 @@
module main module main
// This prelude is loaded in every v program compiled with -live, // This prelude is loaded in every v program compiled with -live,
// but only for the main executable. // but only for the main execuast.
import v.live.executable import v.live.executable
const ( const (

View File

@ -1,81 +0,0 @@
import v.table
fn test_idx() {
mut t := table.new_type(table.void_type_idx)
assert t.idx() == table.void_type_idx
t = table.new_type(table.i8_type_idx)
assert t.idx() == table.i8_type_idx
}
fn test_muls() {
mut t := table.new_type(table.void_type_idx)
idx := t.idx()
assert t.nr_muls() == 0
for i in 0 .. 32 {
t = t.set_nr_muls(i)
assert t.nr_muls() == i
}
t = t.set_nr_muls(0)
assert t.nr_muls() == 0
assert t.is_ptr() == false
t = t.to_ptr()
assert t.nr_muls() == 1
assert t.is_ptr() == true
t = t.to_ptr()
assert t.nr_muls() == 2
assert t.is_ptr() == true
t = t.deref()
assert t.nr_muls() == 1
assert t.is_ptr() == true
t = t.deref()
assert t.nr_muls() == 0
assert t.is_ptr() == false
assert t.idx() == idx
}
fn test_flags() {
mut t := table.new_type(table.void_type_idx)
idx := t.idx()
nr_muls := t.nr_muls()
t = t.set_flag(table.TypeFlag.optional)
assert t.has_flag(table.TypeFlag.optional) == true
assert t.has_flag(table.TypeFlag.variadic) == false
assert t.has_flag(table.TypeFlag.generic) == false
t = t.set_flag(table.TypeFlag.variadic)
assert t.has_flag(table.TypeFlag.optional) == true
assert t.has_flag(table.TypeFlag.variadic) == true
assert t.has_flag(table.TypeFlag.generic) == false
t = t.set_flag(table.TypeFlag.generic)
assert t.has_flag(table.TypeFlag.optional) == true
assert t.has_flag(table.TypeFlag.variadic) == true
assert t.has_flag(table.TypeFlag.generic) == true
assert t.idx() == idx
assert t.nr_muls() == nr_muls
t = t.clear_flag(table.TypeFlag.optional)
assert t.has_flag(table.TypeFlag.optional) == false
assert t.has_flag(table.TypeFlag.variadic) == true
assert t.has_flag(table.TypeFlag.generic) == true
t = t.clear_flag(table.TypeFlag.variadic)
assert t.has_flag(table.TypeFlag.optional) == false
assert t.has_flag(table.TypeFlag.variadic) == false
assert t.has_flag(table.TypeFlag.generic) == true
t = t.clear_flag(table.TypeFlag.generic)
assert t.has_flag(table.TypeFlag.optional) == false
assert t.has_flag(table.TypeFlag.variadic) == false
assert t.has_flag(table.TypeFlag.generic) == false
assert t.idx() == idx
assert t.nr_muls() == nr_muls
}
fn test_derive() {
mut t := table.new_type(table.i8_type_idx)
t = t.set_flag(table.TypeFlag.generic)
t = t.set_flag(table.TypeFlag.variadic)
t = t.set_nr_muls(10)
mut t2 := table.new_type(table.i16_type_idx)
t2 = t2.derive(t)
assert t2.has_flag(table.TypeFlag.optional) == false
assert t2.has_flag(table.TypeFlag.variadic) == true
assert t2.has_flag(table.TypeFlag.generic) == true
assert t2.nr_muls() == 10
}

View File

@ -16,7 +16,7 @@ fn get_foo() Foo {
} }
/* /*
// TODO: Fix this. It 'works' only with tcc, but is not stable. // TODO: Fix this. It 'works' only with tcc, but is not sast.
fn test_ref_fn_arg() { fn test_ref_fn_arg() {
process_foo(get_foo()) process_foo(get_foo())
println(3434) println(3434)

View File

@ -18,7 +18,7 @@ fn (p Point) draw() string {
} }
// Note: this helper function forced the compiler to generate an // Note: this helper function forced the compiler to generate an
// interface dispatch table. Now, it should not be needed anymore, // interface dispatch ast. Now, it should not be needed anymore,
// but it is better to test it too, to prevent future interface regressions. // but it is better to test it too, to prevent future interface regressions.
fn (x Point) tointerface() Drawable { fn (x Point) tointerface() Drawable {
return x return x

View File

@ -458,7 +458,7 @@ pub fn (kind Kind) is_infix() bool {
.right_shift, .arrow] .right_shift, .arrow]
} }
// Pass table.builtin_type_names // Pass ast.builtin_type_names
// Note: can't import table here due to circular module dependency // Note: can't import table here due to circular module dependency
pub fn (tok &Token) can_start_type(builtin_type_names []string) bool { pub fn (tok &Token) can_start_type(builtin_type_names []string) bool {
match tok.kind { match tok.kind {