mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
v2: consts, $if, attributes, globals, if/for type check, prefs
This commit is contained in:
parent
7808f4c272
commit
d87cb3f672
@ -81,10 +81,10 @@ pub fn eprintln(s string) {
|
|||||||
panic('eprintln(NIL)')
|
panic('eprintln(NIL)')
|
||||||
}
|
}
|
||||||
$if !windows {
|
$if !windows {
|
||||||
C.fflush(stdout)
|
C.fflush(C.stdout)
|
||||||
C.fflush(stderr)
|
C.fflush(C.stderr)
|
||||||
C.fprintf(stderr, '%.*s\n', s.len, s.str)
|
C.fprintf(C.stderr, '%.*s\n', s.len, s.str)
|
||||||
C.fflush(stderr)
|
C.fflush(C.stderr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// TODO issues with stderr and cross compiling for Linux
|
// TODO issues with stderr and cross compiling for Linux
|
||||||
@ -96,10 +96,10 @@ pub fn eprint(s string) {
|
|||||||
panic('eprint(NIL)')
|
panic('eprint(NIL)')
|
||||||
}
|
}
|
||||||
$if !windows {
|
$if !windows {
|
||||||
C.fflush(stdout)
|
C.fflush(C.stdout)
|
||||||
C.fflush(stderr)
|
C.fflush(C.stderr)
|
||||||
C.fprintf(stderr, '%.*s', s.len, s.str)
|
C.fprintf(C.stderr, '%.*s', s.len, s.str)
|
||||||
C.fflush(stderr)
|
C.fflush(C.stderr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
print(s)
|
print(s)
|
||||||
@ -124,6 +124,8 @@ pub fn print(s string) {
|
|||||||
__global total_m i64=0
|
__global total_m i64=0
|
||||||
__global nr_mallocs int=0
|
__global nr_mallocs int=0
|
||||||
|
|
||||||
|
fn looo(){} // TODO remove, [ pratt
|
||||||
|
|
||||||
[unsafe_fn]
|
[unsafe_fn]
|
||||||
pub fn malloc(n int) byteptr {
|
pub fn malloc(n int) byteptr {
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
|
@ -8,12 +8,12 @@ import (
|
|||||||
v.table
|
v.table
|
||||||
)
|
)
|
||||||
|
|
||||||
pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral |
|
pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral |
|
||||||
FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr |
|
FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr |
|
||||||
AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr
|
AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr
|
||||||
|
|
||||||
pub type Stmt = VarDecl | FnDecl | Return | Module | Import | ExprStmt |
|
pub type Stmt = VarDecl | GlobalDecl | FnDecl | Return | Module | Import | ExprStmt |
|
||||||
ForStmt | StructDecl | ForCStmt | ForInStmt
|
ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr
|
||||||
// | IncDecStmt k
|
// | IncDecStmt k
|
||||||
// Stand-alone expression in a statement list.
|
// Stand-alone expression in a statement list.
|
||||||
pub struct ExprStmt {
|
pub struct ExprStmt {
|
||||||
@ -63,7 +63,13 @@ pub struct Field {
|
|||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
// type_idx int
|
// type_idx int
|
||||||
ti table.Type
|
typ table.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ConstDecl {
|
||||||
|
pub:
|
||||||
|
fields []Field
|
||||||
|
exprs []Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct StructDecl {
|
pub struct StructDecl {
|
||||||
@ -159,6 +165,14 @@ mut:
|
|||||||
pos token.Position
|
pos token.Position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct GlobalDecl {
|
||||||
|
pub:
|
||||||
|
name string
|
||||||
|
expr Expr
|
||||||
|
mut:
|
||||||
|
typ table.Type
|
||||||
|
}
|
||||||
|
|
||||||
pub struct File {
|
pub struct File {
|
||||||
pub:
|
pub:
|
||||||
mod Module
|
mod Module
|
||||||
@ -178,6 +192,7 @@ type IdentInfo = IdentVar
|
|||||||
pub enum IdentKind {
|
pub enum IdentKind {
|
||||||
blank_ident
|
blank_ident
|
||||||
variable
|
variable
|
||||||
|
constant
|
||||||
}
|
}
|
||||||
|
|
||||||
// A single identifier
|
// A single identifier
|
||||||
@ -232,6 +247,7 @@ pub:
|
|||||||
// op token.Kind
|
// op token.Kind
|
||||||
left Expr
|
left Expr
|
||||||
index Expr // [0], [start..end] etc
|
index Expr // [0], [start..end] etc
|
||||||
|
typ table.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IfExpr {
|
pub struct IfExpr {
|
||||||
@ -242,12 +258,21 @@ pub:
|
|||||||
else_stmts []Stmt
|
else_stmts []Stmt
|
||||||
ti table.Type
|
ti table.Type
|
||||||
left Expr // `a` in `a := if ...`
|
left Expr // `a` in `a := if ...`
|
||||||
|
pos token.Position
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CompIf {
|
||||||
|
pub:
|
||||||
|
cond Expr
|
||||||
|
stmts []Stmt
|
||||||
|
else_stmts []Stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ForStmt {
|
pub struct ForStmt {
|
||||||
pub:
|
pub:
|
||||||
cond Expr
|
cond Expr
|
||||||
stmts []Stmt
|
stmts []Stmt
|
||||||
|
pos token.Position
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ForInStmt {
|
pub struct ForInStmt {
|
||||||
@ -280,6 +305,11 @@ pub:
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// e.g. `[unsafe_fn]`
|
||||||
|
pub struct Attr {
|
||||||
|
pub:
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
pub struct AssignExpr {
|
pub struct AssignExpr {
|
||||||
pub:
|
pub:
|
||||||
|
@ -68,6 +68,9 @@ pub fn (c &Checker) infix_expr(infix_expr ast.InfixExpr) table.Type {
|
|||||||
// c.error('infix expr: cannot use `$infix_expr.right_type.name` as `$infix_expr.left_type.name`', infix_expr.pos)
|
// c.error('infix expr: cannot use `$infix_expr.right_type.name` as `$infix_expr.left_type.name`', infix_expr.pos)
|
||||||
c.error('infix expr: cannot use `$left_ti.name` as `$right_ti.name`', infix_expr.pos)
|
c.error('infix expr: cannot use `$left_ti.name` as `$right_ti.name`', infix_expr.pos)
|
||||||
}
|
}
|
||||||
|
if infix_expr.op.is_relational() {
|
||||||
|
return table.bool_type
|
||||||
|
}
|
||||||
return left_ti
|
return left_ti
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,111 +198,120 @@ fn (c &Checker) stmt(node ast.Stmt) {
|
|||||||
ast.VarDecl {
|
ast.VarDecl {
|
||||||
typ := c.expr(it.expr)
|
typ := c.expr(it.expr)
|
||||||
// println('var decl $typ.name it.typ=$it.typ.name $it.pos.line_nr')
|
// println('var decl $typ.name it.typ=$it.typ.name $it.pos.line_nr')
|
||||||
if it.typ.kind == .unresolved {
|
// if it.typ.kind == .unresolved {
|
||||||
// it.ti = typ
|
// it.ti = typ
|
||||||
// println('unresolved var')
|
// println('unresolved var')
|
||||||
}
|
// }
|
||||||
|
}
|
||||||
|
ast.ForStmt {
|
||||||
|
typ := c.expr(it.cond)
|
||||||
|
if typ.kind != .bool {
|
||||||
|
c.error('non-bool used as for condition', it.pos)
|
||||||
}
|
}
|
||||||
ast.ForStmt {
|
for stmt in it.stmts {
|
||||||
c.expr(it.cond)
|
c.stmt(stmt)
|
||||||
for stmt in it.stmts {
|
|
||||||
c.stmt(stmt)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ast.ForCStmt {
|
}
|
||||||
c.stmt(it.init)
|
ast.ForCStmt {
|
||||||
c.expr(it.cond)
|
c.stmt(it.init)
|
||||||
c.stmt(it.inc)
|
c.expr(it.cond)
|
||||||
for stmt in it.stmts {
|
c.stmt(it.inc)
|
||||||
c.stmt(stmt)
|
for stmt in it.stmts {
|
||||||
}
|
c.stmt(stmt)
|
||||||
}
|
}
|
||||||
// ast.StructDecl {}
|
}
|
||||||
ast.ExprStmt {
|
// ast.StructDecl {}
|
||||||
c.expr(it.expr)
|
ast.ExprStmt {
|
||||||
}
|
c.expr(it.expr)
|
||||||
else {}
|
}
|
||||||
}
|
else {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (c &Checker) expr(node ast.Expr) table.Type {
|
pub fn (c &Checker) expr(node ast.Expr) table.Type {
|
||||||
match node {
|
match node {
|
||||||
ast.AssignExpr {
|
ast.AssignExpr {
|
||||||
c.check_assign_expr(it)
|
c.check_assign_expr(it)
|
||||||
}
|
}
|
||||||
ast.IntegerLiteral {
|
ast.IntegerLiteral {
|
||||||
return table.int_type
|
return table.int_type
|
||||||
}
|
}
|
||||||
// ast.FloatLiteral {}
|
// ast.FloatLiteral {}
|
||||||
ast.PostfixExpr {
|
ast.PostfixExpr {
|
||||||
return c.expr(it.expr)
|
return c.expr(it.expr)
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
ast.UnaryExpr {
|
ast.UnaryExpr {
|
||||||
c.expr(it.left)
|
c.expr(it.left)
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ast.StringLiteral {
|
ast.StringLiteral {
|
||||||
return table.string_type
|
return table.string_type
|
||||||
}
|
}
|
||||||
ast.PrefixExpr {
|
ast.PrefixExpr {
|
||||||
return c.expr(it.right)
|
return c.expr(it.right)
|
||||||
}
|
}
|
||||||
ast.InfixExpr {
|
ast.InfixExpr {
|
||||||
return c.infix_expr(it)
|
return c.infix_expr(it)
|
||||||
}
|
}
|
||||||
ast.StructInit {
|
ast.StructInit {
|
||||||
return c.check_struct_init(it)
|
return c.check_struct_init(it)
|
||||||
}
|
}
|
||||||
ast.CallExpr {
|
ast.CallExpr {
|
||||||
return c.call_expr(it)
|
return c.call_expr(it)
|
||||||
}
|
}
|
||||||
ast.MethodCallExpr {
|
ast.MethodCallExpr {
|
||||||
return c.check_method_call_expr(it)
|
return c.check_method_call_expr(it)
|
||||||
}
|
}
|
||||||
ast.ArrayInit {
|
ast.ArrayInit {
|
||||||
return c.array_init(it)
|
return c.array_init(it)
|
||||||
}
|
}
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
if it.kind == .variable {
|
if it.kind == .variable {
|
||||||
info := it.info as ast.IdentVar
|
info := it.info as ast.IdentVar
|
||||||
if info.typ.kind != .unresolved {
|
if info.typ.kind != .unresolved {
|
||||||
return info.typ
|
return info.typ
|
||||||
}
|
|
||||||
return c.expr(info.expr)
|
|
||||||
}
|
}
|
||||||
return table.void_type
|
return c.expr(info.expr)
|
||||||
}
|
}
|
||||||
// ast.BoolLiteral {}
|
return table.void_type
|
||||||
ast.SelectorExpr {
|
}
|
||||||
return c.selector_expr(it)
|
ast.BoolLiteral {
|
||||||
|
return table.bool_type
|
||||||
|
}
|
||||||
|
ast.SelectorExpr {
|
||||||
|
return c.selector_expr(it)
|
||||||
|
}
|
||||||
|
ast.IndexExpr {
|
||||||
|
// c.expr(it.left)
|
||||||
|
// c.expr(it.index)
|
||||||
|
return it.typ
|
||||||
|
}
|
||||||
|
ast.IfExpr {
|
||||||
|
typ := c.expr(it.cond)
|
||||||
|
if typ.kind != .bool {
|
||||||
|
c.error('non-bool (`$typ.name`) used as if condition', it.pos)
|
||||||
}
|
}
|
||||||
ast.IndexExpr {
|
for i, stmt in it.stmts {
|
||||||
c.expr(it.left)
|
c.stmt(stmt)
|
||||||
c.expr(it.index)
|
|
||||||
}
|
}
|
||||||
ast.IfExpr {
|
if it.else_stmts.len > 0 {
|
||||||
c.expr(it.cond)
|
for stmt in it.else_stmts {
|
||||||
for i, stmt in it.stmts {
|
|
||||||
c.stmt(stmt)
|
c.stmt(stmt)
|
||||||
}
|
}
|
||||||
if it.else_stmts.len > 0 {
|
|
||||||
for stmt in it.else_stmts {
|
|
||||||
c.stmt(stmt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {}
|
}
|
||||||
}
|
else {}
|
||||||
return table.void_type
|
|
||||||
}
|
}
|
||||||
|
return table.void_type
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (c &Checker) error(s string, pos token.Position) {
|
pub fn (c &Checker) error(s string, pos token.Position) {
|
||||||
print_backtrace()
|
print_backtrace()
|
||||||
final_msg_line := '$c.file_name:$pos.line_nr: error: $s'
|
final_msg_line := '$c.file_name:$pos.line_nr: error: $s'
|
||||||
eprintln(final_msg_line)
|
eprintln(final_msg_line)
|
||||||
/*
|
/*
|
||||||
if colored_output {
|
if colored_output {
|
||||||
eprintln(term.bold(term.red(final_msg_line)))
|
eprintln(term.bold(term.red(final_msg_line)))
|
||||||
}else{
|
}else{
|
||||||
@ -307,5 +319,5 @@ fn (c &Checker) stmt(node ast.Stmt) {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,13 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
|||||||
// g.writeln('//// stmt start')
|
// g.writeln('//// stmt start')
|
||||||
match node {
|
match node {
|
||||||
ast.Import {}
|
ast.Import {}
|
||||||
|
ast.ConstDecl {
|
||||||
|
for i, field in it.fields {
|
||||||
|
g.write('$field.typ.name $field.name = ')
|
||||||
|
g.expr(it.exprs[i])
|
||||||
|
g.writeln(';')
|
||||||
|
}
|
||||||
|
}
|
||||||
ast.FnDecl {
|
ast.FnDecl {
|
||||||
g.fn_decl = &it
|
g.fn_decl = &it
|
||||||
is_main := it.name == 'main'
|
is_main := it.name == 'main'
|
||||||
@ -145,7 +152,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
|
|||||||
g.writeln('typedef struct {')
|
g.writeln('typedef struct {')
|
||||||
for field in it.fields {
|
for field in it.fields {
|
||||||
// t := g.table.get_type(field.ti.idx)
|
// t := g.table.get_type(field.ti.idx)
|
||||||
ti := g.table.refresh_ti(field.ti)
|
ti := g.table.refresh_ti(field.typ)
|
||||||
g.writeln('\t$ti.name $field.name;')
|
g.writeln('\t$ti.name $field.name;')
|
||||||
}
|
}
|
||||||
g.writeln('} $it.name;')
|
g.writeln('} $it.name;')
|
||||||
|
@ -6,6 +6,8 @@ multi_return_int_string multi_return();
|
|||||||
void variadic(variadic_int a);
|
void variadic(variadic_int a);
|
||||||
void ensure_cap(int required, int cap);
|
void ensure_cap(int required, int cap);
|
||||||
|
|
||||||
|
int pi = 3;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int age;
|
int age;
|
||||||
} User;
|
} User;
|
||||||
@ -19,6 +21,7 @@ int main() {
|
|||||||
a++;
|
a++;
|
||||||
foo(3);
|
foo(3);
|
||||||
int ak = 10;
|
int ak = 10;
|
||||||
|
int mypi = pi;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
import moda
|
import moda
|
||||||
import modb as mb
|
import modb as mb
|
||||||
|
|
||||||
|
const (
|
||||||
|
pi = 3
|
||||||
|
//s = 'hi'
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
struct User {
|
struct User {
|
||||||
age int
|
age int
|
||||||
}
|
}
|
||||||
@ -15,6 +21,7 @@ fn main() {
|
|||||||
a++
|
a++
|
||||||
foo(3)
|
foo(3)
|
||||||
ak := 10
|
ak := 10
|
||||||
|
mypi := pi
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
user := User{}
|
user := User{}
|
||||||
|
@ -50,7 +50,7 @@ pub fn (p mut Parser) call_args() []ast.Expr {
|
|||||||
return args // ,table.void_ti
|
return args // ,table.void_ti
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) fn_decl() ast.FnDecl {
|
fn (p mut Parser) fn_decl(/*high bool*/) ast.FnDecl {
|
||||||
is_pub := p.tok.kind == .key_pub
|
is_pub := p.tok.kind == .key_pub
|
||||||
if is_pub {
|
if is_pub {
|
||||||
p.next()
|
p.next()
|
||||||
@ -68,14 +68,18 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
|||||||
if p.tok.kind == .key_mut {
|
if p.tok.kind == .key_mut {
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
rec_ti = p.parse_ti()
|
rec_ti = p.parse_type()
|
||||||
p.table.register_var(table.Var{
|
p.table.register_var(table.Var{
|
||||||
name: rec_name
|
name: rec_name
|
||||||
typ: rec_ti
|
typ: rec_ti
|
||||||
})
|
})
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
}
|
}
|
||||||
name := p.check_name()
|
mut name := ''
|
||||||
|
if p.tok.kind == .name {
|
||||||
|
// TODO
|
||||||
|
name = p.check_name()
|
||||||
|
}
|
||||||
// println('fn decl $name')
|
// println('fn decl $name')
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
// Args
|
// Args
|
||||||
@ -88,7 +92,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
|||||||
p.check(.comma)
|
p.check(.comma)
|
||||||
arg_names << p.check_name()
|
arg_names << p.check_name()
|
||||||
}
|
}
|
||||||
ti := p.parse_ti()
|
ti := p.parse_type()
|
||||||
for arg_name in arg_names {
|
for arg_name in arg_names {
|
||||||
arg := table.Var{
|
arg := table.Var{
|
||||||
name: arg_name
|
name: arg_name
|
||||||
@ -112,7 +116,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
|||||||
// Return type
|
// Return type
|
||||||
mut typ := table.void_type
|
mut typ := table.void_type
|
||||||
if p.tok.kind in [.name, .lpar] {
|
if p.tok.kind in [.name, .lpar] {
|
||||||
typ = p.parse_ti()
|
typ = p.parse_type()
|
||||||
p.return_type = typ
|
p.return_type = typ
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -144,7 +148,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
|||||||
is_pub: is_pub
|
is_pub: is_pub
|
||||||
receiver: ast.Field{
|
receiver: ast.Field{
|
||||||
name: rec_name
|
name: rec_name
|
||||||
ti: rec_ti
|
typ: rec_ti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,13 +13,13 @@ pub fn (p mut Parser) parse_array_ti(nr_muls int) table.Type {
|
|||||||
if p.tok.kind == .number {
|
if p.tok.kind == .number {
|
||||||
size := p.tok.lit.int()
|
size := p.tok.lit.int()
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
elem_ti := p.parse_ti()
|
elem_ti := p.parse_type()
|
||||||
idx,name := p.table.find_or_register_array_fixed(&elem_ti, size, 1)
|
idx,name := p.table.find_or_register_array_fixed(&elem_ti, size, 1)
|
||||||
return table.new_type(.array_fixed, name, idx, nr_muls)
|
return table.new_type(.array_fixed, name, idx, nr_muls)
|
||||||
}
|
}
|
||||||
// array
|
// array
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
elem_ti := p.parse_ti()
|
elem_ti := p.parse_type()
|
||||||
mut nr_dims := 1
|
mut nr_dims := 1
|
||||||
for p.tok.kind == .lsbr {
|
for p.tok.kind == .lsbr {
|
||||||
p.check(.lsbr)
|
p.check(.lsbr)
|
||||||
@ -33,9 +33,9 @@ pub fn (p mut Parser) parse_array_ti(nr_muls int) table.Type {
|
|||||||
pub fn (p mut Parser) parse_map_ti(nr_muls int) table.Type {
|
pub fn (p mut Parser) parse_map_ti(nr_muls int) table.Type {
|
||||||
p.next()
|
p.next()
|
||||||
p.check(.lsbr)
|
p.check(.lsbr)
|
||||||
key_ti := p.parse_ti()
|
key_ti := p.parse_type()
|
||||||
p.check(.rsbr)
|
p.check(.rsbr)
|
||||||
value_ti := p.parse_ti()
|
value_ti := p.parse_type()
|
||||||
idx,name := p.table.find_or_register_map(&key_ti, &value_ti)
|
idx,name := p.table.find_or_register_map(&key_ti, &value_ti)
|
||||||
return table.new_type(.map, name, idx, nr_muls)
|
return table.new_type(.map, name, idx, nr_muls)
|
||||||
}
|
}
|
||||||
@ -44,7 +44,7 @@ pub fn (p mut Parser) parse_multi_return_ti() table.Type {
|
|||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
mut mr_tis := []table.Type
|
mut mr_tis := []table.Type
|
||||||
for {
|
for {
|
||||||
mr_ti := p.parse_ti()
|
mr_ti := p.parse_type()
|
||||||
mr_tis << mr_ti
|
mr_tis << mr_ti
|
||||||
if p.tok.kind == .comma {
|
if p.tok.kind == .comma {
|
||||||
p.check(.comma)
|
p.check(.comma)
|
||||||
@ -60,12 +60,18 @@ pub fn (p mut Parser) parse_multi_return_ti() table.Type {
|
|||||||
|
|
||||||
pub fn (p mut Parser) parse_variadic_ti() table.Type {
|
pub fn (p mut Parser) parse_variadic_ti() table.Type {
|
||||||
p.check(.ellipsis)
|
p.check(.ellipsis)
|
||||||
variadic_ti := p.parse_ti()
|
variadic_ti := p.parse_type()
|
||||||
idx,name := p.table.find_or_register_variadic(&variadic_ti)
|
idx,name := p.table.find_or_register_variadic(&variadic_ti)
|
||||||
return table.new_type(.variadic, name, idx, 0)
|
return table.new_type(.variadic, name, idx, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (p mut Parser) parse_ti() table.Type {
|
pub fn (p mut Parser) parse_fn_type() table.Type {
|
||||||
|
//p.check(.key_fn)
|
||||||
|
p.fn_decl()
|
||||||
|
return table.int_type
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (p mut Parser) parse_type() table.Type {
|
||||||
mut nr_muls := 0
|
mut nr_muls := 0
|
||||||
for p.tok.kind == .amp {
|
for p.tok.kind == .amp {
|
||||||
p.check(.amp)
|
p.check(.amp)
|
||||||
@ -73,6 +79,10 @@ pub fn (p mut Parser) parse_ti() table.Type {
|
|||||||
}
|
}
|
||||||
name := p.tok.lit
|
name := p.tok.lit
|
||||||
match p.tok.kind {
|
match p.tok.kind {
|
||||||
|
// func
|
||||||
|
.key_fn {
|
||||||
|
return p.parse_fn_type()
|
||||||
|
}
|
||||||
// array
|
// array
|
||||||
.lsbr {
|
.lsbr {
|
||||||
return p.parse_array_ti(nr_muls)
|
return p.parse_array_ti(nr_muls)
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
v.ast
|
v.ast
|
||||||
v.token
|
v.token
|
||||||
v.table
|
v.table
|
||||||
|
v.pref
|
||||||
term
|
term
|
||||||
os
|
os
|
||||||
)
|
)
|
||||||
@ -35,6 +36,9 @@ mut:
|
|||||||
//
|
//
|
||||||
// prefix_parse_fns []PrefixParseFn
|
// prefix_parse_fns []PrefixParseFn
|
||||||
inside_if bool
|
inside_if bool
|
||||||
|
pref &pref.Preferences // Preferences shared from V struct
|
||||||
|
builtin_mod bool
|
||||||
|
mod string
|
||||||
}
|
}
|
||||||
|
|
||||||
// for tests
|
// for tests
|
||||||
@ -59,6 +63,8 @@ pub fn parse_file(path string, table &table.Table) ast.File {
|
|||||||
scanner: scanner.new_scanner(text)
|
scanner: scanner.new_scanner(text)
|
||||||
table: table
|
table: table
|
||||||
file_name: path
|
file_name: path
|
||||||
|
pref: &pref.Preferences{}
|
||||||
|
builtin_mod: true
|
||||||
}
|
}
|
||||||
p.read_first_token()
|
p.read_first_token()
|
||||||
// module decl
|
// module decl
|
||||||
@ -170,6 +176,12 @@ pub fn (p mut Parser) top_stmt() ast.Stmt {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.lsbr {
|
||||||
|
return p.attr()
|
||||||
|
}
|
||||||
|
.key_global {
|
||||||
|
return p.global_decl()
|
||||||
|
}
|
||||||
.key_const {
|
.key_const {
|
||||||
return p.const_decl()
|
return p.const_decl()
|
||||||
}
|
}
|
||||||
@ -179,16 +191,12 @@ pub fn (p mut Parser) top_stmt() ast.Stmt {
|
|||||||
.key_struct {
|
.key_struct {
|
||||||
return p.struct_decl()
|
return p.struct_decl()
|
||||||
}
|
}
|
||||||
.lsbr {
|
.dollar {
|
||||||
p.next()
|
return p.comp_if()
|
||||||
p.check(.name)
|
|
||||||
p.check(.rsbr)
|
|
||||||
return ast.Module{}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p.error('bad top level statement')
|
p.error('bad top level statement')
|
||||||
return ast.Module{} // silence C warning
|
return ast.Stmt{}
|
||||||
// exit(0)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -204,6 +212,9 @@ pub fn (p mut Parser) stmt() ast.Stmt {
|
|||||||
.key_return {
|
.key_return {
|
||||||
return p.return_stmt()
|
return p.return_stmt()
|
||||||
}
|
}
|
||||||
|
.dollar {
|
||||||
|
return p.comp_if()
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// `x := ...`
|
// `x := ...`
|
||||||
if p.tok.kind == .name && p.peek_tok.kind == .decl_assign {
|
if p.tok.kind == .name && p.peek_tok.kind == .decl_assign {
|
||||||
@ -218,6 +229,22 @@ pub fn (p mut Parser) stmt() ast.Stmt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (p mut Parser) comp_if() ast.CompIf {
|
||||||
|
p.next()
|
||||||
|
p.check(.key_if)
|
||||||
|
if p.tok.kind == .not {
|
||||||
|
p.next()
|
||||||
|
}
|
||||||
|
p.check_name()
|
||||||
|
p.parse_block()
|
||||||
|
if p.tok.kind == .dollar && p.peek_tok.kind == .key_else {
|
||||||
|
p.next()
|
||||||
|
p.check(.key_else)
|
||||||
|
p.parse_block()
|
||||||
|
}
|
||||||
|
return ast.CompIf{}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (p mut Parser) assign_expr(left ast.Expr) ast.AssignExpr {
|
pub fn (p mut Parser) assign_expr(left ast.Expr) ast.AssignExpr {
|
||||||
op := p.tok.kind
|
op := p.tok.kind
|
||||||
p.next()
|
p.next()
|
||||||
@ -231,6 +258,15 @@ pub fn (p mut Parser) assign_expr(left ast.Expr) ast.AssignExpr {
|
|||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (p mut Parser) attr() ast.Attr {
|
||||||
|
p.check(.lsbr)
|
||||||
|
name := p.check_name()
|
||||||
|
p.check(.rsbr)
|
||||||
|
return ast.Attr{
|
||||||
|
name: name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn (p mut Parser) range_expr(low ast.Expr) ast.Expr {
|
fn (p mut Parser) range_expr(low ast.Expr) ast.Expr {
|
||||||
// ,table.Type) {
|
// ,table.Type) {
|
||||||
p.next()
|
p.next()
|
||||||
@ -310,7 +346,8 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
|
|||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
// mut typ := table.void_ti
|
// mut typ := table.void_ti
|
||||||
mut typ := table.unresolved_type
|
mut typ := table.unresolved_type
|
||||||
if p.tok.lit == 'C' {
|
is_c := p.tok.lit == 'C' && p.peek_tok.kind == .dot
|
||||||
|
if is_c {
|
||||||
p.next()
|
p.next()
|
||||||
p.check(.dot)
|
p.check(.dot)
|
||||||
}
|
}
|
||||||
@ -327,7 +364,7 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
|
|||||||
}
|
}
|
||||||
// struct init
|
// struct init
|
||||||
else if p.peek_tok.kind == .lcbr && (p.tok.lit[0].is_capital() || p.tok.lit in ['array', 'string']) {
|
else if p.peek_tok.kind == .lcbr && (p.tok.lit[0].is_capital() || p.tok.lit in ['array', 'string']) {
|
||||||
typ = p.parse_ti()
|
typ = p.parse_type()
|
||||||
// p.warn('struct init typ=$typ.name')
|
// p.warn('struct init typ=$typ.name')
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
mut field_names := []string
|
mut field_names := []string
|
||||||
@ -347,13 +384,13 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
|
|||||||
}
|
}
|
||||||
p.check(.rcbr)
|
p.check(.rcbr)
|
||||||
}
|
}
|
||||||
// variable
|
|
||||||
else {
|
else {
|
||||||
// p.warn('name ')
|
// p.warn('name ')
|
||||||
// left := p.parse_ident()
|
// left := p.parse_ident()
|
||||||
mut ident := ast.Ident{
|
mut ident := ast.Ident{
|
||||||
name: p.tok.lit
|
name: p.tok.lit
|
||||||
}
|
}
|
||||||
|
// variable
|
||||||
if var := p.table.find_var(p.tok.lit) {
|
if var := p.table.find_var(p.tok.lit) {
|
||||||
typ = var.typ
|
typ = var.typ
|
||||||
ident.kind = .variable
|
ident.kind = .variable
|
||||||
@ -361,18 +398,40 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
|
|||||||
typ: typ
|
typ: typ
|
||||||
name: ident.name
|
name: ident.name
|
||||||
// expr: p.expr(0)// var.expr
|
// expr: p.expr(0)// var.expr
|
||||||
|
|
||||||
}
|
}
|
||||||
// ident.ti = ti
|
// ident.ti = ti
|
||||||
node = ident
|
node = ident
|
||||||
p.next()
|
p.next()
|
||||||
}else{
|
}else{
|
||||||
// Function object (not a call), e.g. `onclick(my_click)`
|
if is_c {
|
||||||
p.table.find_fn(p.tok.lit) or {
|
typ = table.int_type
|
||||||
p.error('name expr unknown variable `$p.tok.lit`')
|
ident.info = ast.IdentVar{
|
||||||
exit(0)
|
typ: typ
|
||||||
|
name: ident.name
|
||||||
|
}
|
||||||
|
node = ident
|
||||||
|
p.next()
|
||||||
|
return node,typ
|
||||||
|
}
|
||||||
|
// const
|
||||||
|
if c := p.table.find_const(p.tok.lit) {
|
||||||
|
typ = c.typ
|
||||||
|
ident.kind = .constant
|
||||||
|
ident.info = ast.IdentVar{
|
||||||
|
typ: typ
|
||||||
|
name: ident.name
|
||||||
|
}
|
||||||
|
node = ident
|
||||||
|
p.next()
|
||||||
|
}else{
|
||||||
|
// Function object (not a call), e.g. `onclick(my_click)`
|
||||||
|
p.table.find_fn(p.tok.lit) or {
|
||||||
|
p.error('name expr unknown identifier `$p.tok.lit`')
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
|
p.next()
|
||||||
}
|
}
|
||||||
p.next()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return node,typ
|
return node,typ
|
||||||
@ -505,6 +564,7 @@ fn (p mut Parser) index_expr(left ast.Expr, typ_ table.Type) (ast.Expr,table.Typ
|
|||||||
node = ast.IndexExpr{
|
node = ast.IndexExpr{
|
||||||
left: left
|
left: left
|
||||||
index: index_expr
|
index: index_expr
|
||||||
|
typ: typ
|
||||||
}
|
}
|
||||||
// return node
|
// return node
|
||||||
return node,typ
|
return node,typ
|
||||||
@ -572,6 +632,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
|||||||
stmts := p.parse_block()
|
stmts := p.parse_block()
|
||||||
return ast.ForStmt{
|
return ast.ForStmt{
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
|
pos: p.tok.position()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if p.tok.kind == .key_mut {
|
else if p.tok.kind == .key_mut {
|
||||||
@ -600,9 +661,6 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
|||||||
if p.tok.kind != .semicolon {
|
if p.tok.kind != .semicolon {
|
||||||
mut typ := table.Type{}
|
mut typ := table.Type{}
|
||||||
cond,typ = p.expr(0)
|
cond,typ = p.expr(0)
|
||||||
if typ.kind != .bool {
|
|
||||||
p.error('non-bool used as for condition')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
p.check(.semicolon)
|
p.check(.semicolon)
|
||||||
if p.tok.kind != .lcbr {
|
if p.tok.kind != .lcbr {
|
||||||
@ -630,6 +688,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
|||||||
// println('nr stmts=$stmts.len')
|
// println('nr stmts=$stmts.len')
|
||||||
return ast.ForStmt{
|
return ast.ForStmt{
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
|
pos: p.tok.position()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// `for cond {`
|
// `for cond {`
|
||||||
@ -641,6 +700,7 @@ fn (p mut Parser) for_statement() ast.Stmt {
|
|||||||
return ast.ForStmt{
|
return ast.ForStmt{
|
||||||
cond: cond
|
cond: cond
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
|
pos: p.tok.position()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,12 +710,8 @@ fn (p mut Parser) if_expr() (ast.Expr,table.Type) {
|
|||||||
// }
|
// }
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
p.check(.key_if)
|
p.check(.key_if)
|
||||||
cond,cond_ti := p.expr(0)
|
cond,_ := p.expr(0)
|
||||||
p.inside_if = false
|
p.inside_if = false
|
||||||
// if !p.table.check(table.bool_ti, cond_ti) {
|
|
||||||
if cond_ti.kind != .bool {
|
|
||||||
p.error('non-bool (`$cond_ti.name`) used as if condition')
|
|
||||||
}
|
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block()
|
||||||
mut else_stmts := []ast.Stmt
|
mut else_stmts := []ast.Stmt
|
||||||
if p.tok.kind == .key_else {
|
if p.tok.kind == .key_else {
|
||||||
@ -679,8 +735,9 @@ fn (p mut Parser) if_expr() (ast.Expr,table.Type) {
|
|||||||
stmts: stmts
|
stmts: stmts
|
||||||
else_stmts: else_stmts
|
else_stmts: else_stmts
|
||||||
ti: ti
|
ti: ti
|
||||||
|
pos: p.tok.position()
|
||||||
// left: left
|
// left: left
|
||||||
|
|
||||||
}
|
}
|
||||||
return node,ti
|
return node,ti
|
||||||
}
|
}
|
||||||
@ -708,19 +765,19 @@ fn (p mut Parser) string_expr() (ast.Expr,table.Type) {
|
|||||||
|
|
||||||
fn (p mut Parser) array_init() (ast.Expr,table.Type) {
|
fn (p mut Parser) array_init() (ast.Expr,table.Type) {
|
||||||
p.check(.lsbr)
|
p.check(.lsbr)
|
||||||
mut val_ti := table.void_type
|
mut val_type := table.void_type
|
||||||
mut exprs := []ast.Expr
|
mut exprs := []ast.Expr
|
||||||
for i := 0; p.tok.kind != .rsbr; i++ {
|
for i := 0; p.tok.kind != .rsbr; i++ {
|
||||||
expr,ti := p.expr(0)
|
expr,typ := p.expr(0)
|
||||||
exprs << expr
|
exprs << expr
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
val_ti = ti
|
val_type = typ
|
||||||
}
|
}
|
||||||
if p.tok.kind == .comma {
|
if p.tok.kind == .comma {
|
||||||
p.check(.comma)
|
p.check(.comma)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
type_idx,type_name := p.table.find_or_register_array(val_ti, 1)
|
type_idx,type_name := p.table.find_or_register_array(val_type, 1)
|
||||||
array_ti := table.new_type(.array, type_name, type_idx, 0)
|
array_ti := table.new_type(.array, type_name, type_idx, 0)
|
||||||
mut node := ast.Expr{}
|
mut node := ast.Expr{}
|
||||||
node = ast.ArrayInit{
|
node = ast.ArrayInit{
|
||||||
@ -792,20 +849,31 @@ fn (p mut Parser) import_stmt() []ast.Import {
|
|||||||
return imports
|
return imports
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
fn (p mut Parser) const_decl() ast.ConstDecl {
|
||||||
// fn (p mut Parser) const_decl() ast... {
|
|
||||||
fn (p mut Parser) const_decl() ast.Stmt {
|
|
||||||
p.check(.key_const)
|
p.check(.key_const)
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
|
mut fields := []ast.Field
|
||||||
|
mut exprs := []ast.Expr
|
||||||
for p.tok.kind != .rpar {
|
for p.tok.kind != .rpar {
|
||||||
name := p.check_name()
|
name := p.check_name()
|
||||||
println('const: $name')
|
println('const: $name')
|
||||||
p.check(.assign)
|
p.check(.assign)
|
||||||
_,_ := p.expr(0)
|
expr,typ := p.expr(0)
|
||||||
// expr, ti := p.expr(0)
|
fields << ast.Field{
|
||||||
|
name: name
|
||||||
|
typ: typ
|
||||||
|
}
|
||||||
|
exprs << expr
|
||||||
|
p.table.register_const(table.Var{
|
||||||
|
name: name
|
||||||
|
typ: typ
|
||||||
|
})
|
||||||
}
|
}
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
return ast.Stmt{}
|
return ast.ConstDecl{
|
||||||
|
fields: fields
|
||||||
|
exprs: exprs
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (p mut Parser) struct_decl() ast.StructDecl {
|
fn (p mut Parser) struct_decl() ast.StructDecl {
|
||||||
@ -824,15 +892,15 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
|
|||||||
p.check(.colon)
|
p.check(.colon)
|
||||||
}
|
}
|
||||||
field_name := p.check_name()
|
field_name := p.check_name()
|
||||||
ti := p.parse_ti()
|
ti := p.parse_type()
|
||||||
ast_fields << ast.Field{
|
ast_fields << ast.Field{
|
||||||
name: field_name
|
name: field_name
|
||||||
ti: ti
|
typ: ti
|
||||||
}
|
}
|
||||||
fields << table.Field{
|
fields << table.Field{
|
||||||
name: field_name
|
name: field_name
|
||||||
// type_idx: ti.idx
|
// type_idx: ti.idx
|
||||||
|
|
||||||
ti: ti
|
ti: ti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -905,7 +973,7 @@ fn (p mut Parser) var_decl() ast.VarDecl {
|
|||||||
name: name
|
name: name
|
||||||
is_mut: is_mut
|
is_mut: is_mut
|
||||||
// expr: expr
|
// expr: expr
|
||||||
|
|
||||||
typ: typ
|
typ: typ
|
||||||
})
|
})
|
||||||
p.warn('var decl name=$name typ=$typ.name')
|
p.warn('var decl name=$name typ=$typ.name')
|
||||||
@ -913,7 +981,7 @@ fn (p mut Parser) var_decl() ast.VarDecl {
|
|||||||
node := ast.VarDecl{
|
node := ast.VarDecl{
|
||||||
name: name
|
name: name
|
||||||
expr: expr // p.expr(token.lowest_prec)
|
expr: expr // p.expr(token.lowest_prec)
|
||||||
|
|
||||||
is_mut: is_mut
|
is_mut: is_mut
|
||||||
typ: typ
|
typ: typ
|
||||||
pos: p.tok.position()
|
pos: p.tok.position()
|
||||||
@ -921,6 +989,40 @@ fn (p mut Parser) var_decl() ast.VarDecl {
|
|||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (p mut Parser) global_decl() ast.GlobalDecl {
|
||||||
|
if !p.pref.translated && !p.pref.is_live && !p.builtin_mod && !p.pref.building_v && p.mod != 'ui' && p.mod != 'gg2' && p.mod != 'uiold' && !os.getwd().contains('/volt') && !p.pref.enable_globals {
|
||||||
|
p.error('use `v --enable-globals ...` to enable globals')
|
||||||
|
}
|
||||||
|
p.next()
|
||||||
|
name := p.check_name()
|
||||||
|
println(name)
|
||||||
|
typ := p.parse_type()
|
||||||
|
if p.tok.kind == .assign {
|
||||||
|
p.next()
|
||||||
|
p.expr(0)
|
||||||
|
}
|
||||||
|
p.table.register_global(name, typ)
|
||||||
|
// p.genln(p.table.cgen_name_type_pair(name, typ))
|
||||||
|
/*
|
||||||
|
mut g := p.table.cgen_name_type_pair(name, typ)
|
||||||
|
if p.tok == .assign {
|
||||||
|
p.next()
|
||||||
|
g += ' = '
|
||||||
|
_,expr := p.tmp_expr()
|
||||||
|
g += expr
|
||||||
|
}
|
||||||
|
// p.genln('; // global')
|
||||||
|
g += '; // global'
|
||||||
|
if !p.cgen.nogen {
|
||||||
|
p.cgen.consts << g
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
return ast.GlobalDecl{
|
||||||
|
name: name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn verror(s string) {
|
fn verror(s string) {
|
||||||
println(s)
|
println(s)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
68
vlib/v/pref/pref.v
Normal file
68
vlib/v/pref/pref.v
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
|
// Use of this source code is governed by an MIT license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
module pref
|
||||||
|
|
||||||
|
pub enum BuildMode {
|
||||||
|
// `v program.v'
|
||||||
|
// Build user code only, and add pre-compiled vlib (`cc program.o builtin.o os.o...`)
|
||||||
|
default_mode
|
||||||
|
// `v -lib ~/v/os`
|
||||||
|
// build any module (generate os.o + os.vh)
|
||||||
|
build_module
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct Preferences {
|
||||||
|
pub mut:
|
||||||
|
build_mode BuildMode
|
||||||
|
// nofmt bool // disable vfmt
|
||||||
|
is_test bool // `v test string_test.v`
|
||||||
|
is_script bool // single file mode (`v program.v`), main function can be skipped
|
||||||
|
is_live bool // main program that contains live/hot code
|
||||||
|
is_solive bool // a shared library, that will be used in a -live main program
|
||||||
|
is_so bool // an ordinary shared library, -shared, no matter if it is live or not
|
||||||
|
is_prof bool // benchmark every function
|
||||||
|
translated bool // `v translate doom.v` are we running V code translated from C? allow globals, ++ expressions, etc
|
||||||
|
is_prod bool // use "-O2"
|
||||||
|
is_verbose bool // print extra information with `v.log()`
|
||||||
|
obfuscate bool // `v -obf program.v`, renames functions to "f_XXX"
|
||||||
|
is_repl bool
|
||||||
|
is_run bool
|
||||||
|
show_c_cmd bool // `v -show_c_cmd` prints the C command to build program.v.c
|
||||||
|
sanitize bool // use Clang's new "-fsanitize" option
|
||||||
|
is_debug bool // false by default, turned on by -g or -cg, it tells v to pass -g to the C backend compiler.
|
||||||
|
is_vlines bool // turned on by -g, false by default (it slows down .tmp.c generation slightly).
|
||||||
|
is_keep_c bool // -keep_c , tell v to leave the generated .tmp.c alone (since by default v will delete them after c backend finishes)
|
||||||
|
// NB: passing -cg instead of -g will set is_vlines to false and is_g to true, thus making v generate cleaner C files,
|
||||||
|
// which are sometimes easier to debug / inspect manually than the .tmp.c files by plain -g (when/if v line number generation breaks).
|
||||||
|
is_pretty_c bool // -pretty_c , tell v to run clang-format -i over the produced C file, before it is compiled. Use with -keep_c or with -o x.c .
|
||||||
|
is_cache bool // turns on v usage of the module cache to speed up compilation.
|
||||||
|
is_stats bool // `v -stats file_test.v` will produce more detailed statistics for the tests that were run
|
||||||
|
no_auto_free bool // `v -nofree` disable automatic `free()` insertion for better performance in some applications (e.g. compilers)
|
||||||
|
cflags string // Additional options which will be passed to the C compiler.
|
||||||
|
// For example, passing -cflags -Os will cause the C compiler to optimize the generated binaries for size.
|
||||||
|
// You could pass several -cflags XXX arguments. They will be merged with each other.
|
||||||
|
// You can also quote several options at the same time: -cflags '-Os -fno-inline-small-functions'.
|
||||||
|
ccompiler string // the name of the used C compiler
|
||||||
|
building_v bool
|
||||||
|
autofree bool
|
||||||
|
compress bool
|
||||||
|
// skip_builtin bool // Skips re-compilation of the builtin module
|
||||||
|
// to increase compilation time.
|
||||||
|
// This is on by default, since a vast majority of users do not
|
||||||
|
// work on the builtin module itself.
|
||||||
|
// generating_vh bool
|
||||||
|
fast bool // use tcc/x64 codegen
|
||||||
|
enable_globals bool // allow __global for low level code
|
||||||
|
// is_fmt bool
|
||||||
|
is_bare bool
|
||||||
|
user_mod_path string // `v -user_mod_path /Users/user/modules` adds a new lookup path for imported modules
|
||||||
|
vlib_path string
|
||||||
|
vpath string
|
||||||
|
x64 bool
|
||||||
|
output_cross_c bool
|
||||||
|
prealloc bool
|
||||||
|
v2 bool
|
||||||
|
}
|
||||||
|
|
@ -14,6 +14,7 @@ pub mut:
|
|||||||
local_vars []Var
|
local_vars []Var
|
||||||
// fns Hashmap
|
// fns Hashmap
|
||||||
fns map[string]Fn
|
fns map[string]Fn
|
||||||
|
consts map[string]Var
|
||||||
tmp_cnt int
|
tmp_cnt int
|
||||||
imports []string
|
imports []string
|
||||||
}
|
}
|
||||||
@ -27,11 +28,13 @@ pub:
|
|||||||
|
|
||||||
pub struct Var {
|
pub struct Var {
|
||||||
pub:
|
pub:
|
||||||
name string
|
name string
|
||||||
is_mut bool
|
is_mut bool
|
||||||
|
is_const bool
|
||||||
|
is_global bool
|
||||||
// expr ast.Expr
|
// expr ast.Expr
|
||||||
mut:
|
mut:
|
||||||
typ Type
|
typ Type
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_table() &Table {
|
pub fn new_table() &Table {
|
||||||
@ -78,6 +81,23 @@ pub fn (t mut Table) clear_vars() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (t mut Table) register_const(v Var) {
|
||||||
|
t.consts[v.name] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (t mut Table) register_global(name string, typ Type) {
|
||||||
|
t.consts[name] = Var{
|
||||||
|
name: name
|
||||||
|
typ: typ
|
||||||
|
is_const: true
|
||||||
|
is_global: true
|
||||||
|
// mod: p.mod
|
||||||
|
// is_mut: true
|
||||||
|
// idx: -1
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (t mut Table) register_var(v Var) {
|
pub fn (t mut Table) register_var(v Var) {
|
||||||
println('register_var: $v.name - $v.typ.name')
|
println('register_var: $v.name - $v.typ.name')
|
||||||
t.local_vars << v
|
t.local_vars << v
|
||||||
@ -112,6 +132,15 @@ pub fn (t &Table) find_fn(name string) ?Fn {
|
|||||||
return none
|
return none
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn (t &Table) find_const(name string) ?Var {
|
||||||
|
f := t.consts[name]
|
||||||
|
if f.name.str != 0 {
|
||||||
|
// TODO
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
|
||||||
pub fn (t mut Table) register_fn(new_fn Fn) {
|
pub fn (t mut Table) register_fn(new_fn Fn) {
|
||||||
// println('reg fn $new_fn.name nr_args=$new_fn.args.len')
|
// println('reg fn $new_fn.name nr_args=$new_fn.args.len')
|
||||||
t.fns[new_fn.name] = new_fn
|
t.fns[new_fn.name] = new_fn
|
||||||
@ -351,7 +380,7 @@ pub fn (t &Table) check(got, expected &Type) bool {
|
|||||||
// if expected.name == 'array' {
|
// if expected.name == 'array' {
|
||||||
// return true
|
// return true
|
||||||
// }
|
// }
|
||||||
if got.idx != expected.idx {
|
if got.idx != expected.idx && got.name != expected.name {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
Loading…
Reference in New Issue
Block a user