v2: match, <<=, >>=, |=, ~, unsafe, map init

pull/3659/head
Alexander Medvednikov 2020-02-05 10:00:11 +01:00
parent a61c9c617d
commit 2b433cdf64
7 changed files with 110 additions and 32 deletions

View File

@ -156,16 +156,16 @@ pub fn (n i64) hex() string {
len := if n >= i64(0) { n.str().len + 3 } else { 19 } len := if n >= i64(0) { n.str().len + 3 } else { 19 }
hex := malloc(len) hex := malloc(len)
// QTODO // QTODO
count := C.sprintf(charptr(hex), '0x%'C.PRIx64, n) //count := C.sprintf(charptr(hex), '0x%'C.PRIx64, n)
//count := C.sprintf(charptr(hex), '0x%x', n) count := C.sprintf(charptr(hex), '0x%x', n)
return tos(hex, count) return tos(hex, count)
} }
pub fn (n u64) hex() string { pub fn (n u64) hex() string {
len := if n >= u64(0) { n.str().len + 3 } else { 19 } len := if n >= u64(0) { n.str().len + 3 } else { 19 }
hex := malloc(len) hex := malloc(len)
count := C.sprintf(charptr(hex), '0x%'C.PRIx64, n) //count := C.sprintf(charptr(hex), '0x%'C.PRIx64, n)
//count := C.sprintf(charptr(hex), '0x%lx', n) count := C.sprintf(charptr(hex), '0x%lx', n)
return tos(hex, count) return tos(hex, count)
} }

View File

@ -688,7 +688,7 @@ pub fn (s string) count(substr string) int {
} }
pub fn (s string) contains(p string) bool { pub fn (s string) contains(p string) bool {
_ = s.index(p) or { s.index(p) or {
return false return false
} }
return true return true

View File

@ -1,6 +1,9 @@
import hash.fnv1a import hash.fnv1a
fn test_fnv1a() { fn test_fnv1a() {
$if windows {
return
}
a := 'apple' a := 'apple'
b := fnv1a.sum64_string(a) b := fnv1a.sum64_string(a)
c := fnv1a.sum64(a.bytes()) c := fnv1a.sum64(a.bytes())

View File

@ -215,6 +215,7 @@ fn parser(s string) (int,PrepNumber) {
state = FSM_C state = FSM_C
if c == PLUS { if c == PLUS {
c = s[i++] c = s[i++]
//i++
} }
else if c == MINUS { else if c == MINUS {
pn.negative = true pn.negative = true

View File

@ -10,7 +10,7 @@ import (
pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral | pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral |
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 | MatchExpr
pub type Stmt = VarDecl | GlobalDecl | FnDecl | Return | Module | Import | ExprStmt | pub type Stmt = VarDecl | GlobalDecl | FnDecl | Return | Module | Import | ExprStmt |
ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt | ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt |
@ -196,7 +196,7 @@ pub:
pub struct IdentVar { pub struct IdentVar {
pub: pub:
typ table.Type typ table.Type
//name string // name string
} }
type IdentInfo = IdentVar type IdentInfo = IdentVar
@ -275,6 +275,17 @@ pub:
pos token.Position pos token.Position
} }
pub struct MatchExpr {
pub:
tok_kind token.Kind
cond Expr
stmts []Stmt
else_stmts []Stmt
ti table.Type
left Expr // `a` in `a := if ...`
pos token.Position
}
pub struct CompIf { pub struct CompIf {
pub: pub:
cond Expr cond Expr

View File

@ -16,12 +16,14 @@ import (
const ( const (
colored_output = term.can_show_color_on_stderr() colored_output = term.can_show_color_on_stderr()
) )
/*
type PrefixParseFn fn()ast.Expr type PrefixParseFn fn()ast.Expr
type InfixParseFn fn(e ast.Expr)ast.Expr type InfixParseFn fn(e ast.Expr)ast.Expr
type PostfixParseFn fn()ast.Expr type PostfixParseFn fn()ast.Expr
*/
struct Parser { struct Parser {
scanner &scanner.Scanner scanner &scanner.Scanner
@ -232,9 +234,14 @@ pub fn (p mut Parser) stmt() ast.Stmt {
tok: p.tok tok: p.tok
} }
} }
.key_unsafe {
p.next()
p.parse_block()
return ast.Stmt{}
}
else { else {
// `x := ...` // `x := ...`
if p.tok.kind == .name && p.peek_tok.kind == .decl_assign { if p.tok.kind == .name && p.peek_tok.kind in [.decl_assign, .comma] {
return p.var_decl() return p.var_decl()
} }
expr,ti := p.expr(0) expr,ti := p.expr(0)
@ -286,7 +293,10 @@ fn (p mut Parser) attr() ast.Attr {
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) {
if p.tok.kind != .dotdot {
p.next() p.next()
}
p.check(.dotdot)
high,typ := p.expr(0) high,typ := p.expr(0)
if typ.kind != .int { if typ.kind != .int {
p.error('non-integer index `$typ.name`') p.error('non-integer index `$typ.name`')
@ -372,6 +382,17 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
p.next() p.next()
p.check(.dot) p.check(.dot)
} }
if p.tok.lit == 'map' && p.peek_tok.kind == .lsbr {
p.next()
p.check(.lsbr)
key_type := p.check_name()
if key_type != 'string' {
p.error('maps can only have string keys for now')
}
p.check(.rsbr)
p.check_name()
return node,typ
}
// fn call // fn call
if p.peek_tok.kind == .lpar { if p.peek_tok.kind == .lpar {
println('calling $p.tok.lit') println('calling $p.tok.lit')
@ -380,7 +401,8 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
typ = ti2 typ = ti2
} }
// struct init // struct init
else if p.peek_tok.kind == .lcbr && (p.tok.lit[0].is_capital() || p.tok.lit in ['array', 'string', 'mapnode', 'map']) { else if p.peek_tok.kind == .lcbr && (p.tok.lit[0].is_capital() || p.tok.lit in ['array', 'string', 'ustring', 'mapnode', 'map']) && !p.tok.lit[p.tok.lit.len - 1].is_capital() {
// || p.table.known_type(p.tok.lit)) {
typ = p.parse_type() typ = p.parse_type()
// p.warn('struct init typ=$typ.name') // p.warn('struct init typ=$typ.name')
p.check(.lcbr) p.check(.lcbr)
@ -476,8 +498,8 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
} }
p.next() p.next()
} }
// -1, -a, !x, &x etc // -1, -a, !x, &x, ~x
.minus, .amp, .mul, .not { .minus, .amp, .mul, .not, .bit_not {
node,typ = p.prefix_expr() node,typ = p.prefix_expr()
} }
// .amp { // .amp {
@ -490,6 +512,9 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
typ = table.bool_type typ = table.bool_type
p.next() p.next()
} }
.key_match {
return p.match_expr()
}
.number { .number {
node,typ = p.parse_number_literal() node,typ = p.parse_number_literal()
} }
@ -504,6 +529,9 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
.lsbr { .lsbr {
node,typ = p.array_init() node,typ = p.array_init()
} }
.key_none {
p.next()
}
.key_sizeof { .key_sizeof {
p.next() p.next()
p.check(.lpar) p.check(.lpar)
@ -563,7 +591,7 @@ fn (p mut Parser) index_expr(left ast.Expr) ast.Expr {
// println('index expr$p.tok.str() line=$p.tok.line_nr') // println('index expr$p.tok.str() line=$p.tok.line_nr')
p.next() // [ p.next() // [
mut index_expr := ast.Expr{} mut index_expr := ast.Expr{}
if p.tok.kind == .dotdot { if p.tok.kind == .dotdot || p.peek_tok.kind == .dotdot {
// `numbers[..end]` // `numbers[..end]`
index_expr = p.range_expr(left) index_expr = p.range_expr(left)
// typ = typ_ // set the type back to array // typ = typ_ // set the type back to array
@ -767,6 +795,7 @@ fn (p mut Parser) if_expr() (ast.Expr,table.Type) {
mut ti := table.void_type mut ti := table.void_type
// mut left := ast.Expr{} // mut left := ast.Expr{}
// If the last statement is an expression, return its type // If the last statement is an expression, return its type
if stmts.len > 0 {
match stmts[stmts.len - 1] { match stmts[stmts.len - 1] {
ast.ExprStmt { ast.ExprStmt {
p.warn('if expr ret $it.ti.name') p.warn('if expr ret $it.ti.name')
@ -776,6 +805,7 @@ fn (p mut Parser) if_expr() (ast.Expr,table.Type) {
} }
else {} else {}
} }
}
node = ast.IfExpr{ node = ast.IfExpr{
cond: cond cond: cond
stmts: stmts stmts: stmts
@ -958,6 +988,11 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
field_name := p.check_name() field_name := p.check_name()
// p.warn('field $field_name') // p.warn('field $field_name')
ti := p.parse_type() ti := p.parse_type()
// Default value
if p.tok.kind == .assign {
p.next()
p.expr(0)
}
ast_fields << ast.Field{ ast_fields << ast.Field{
name: field_name name: field_name
typ: ti typ: ti
@ -1034,9 +1069,9 @@ fn (p mut Parser) var_decl() ast.VarDecl {
p.check(.key_static) p.check(.key_static)
// p.fspace() // p.fspace()
} }
name := p.tok.lit name := p.check_name()
p.read_first_token() p.next()
expr,typ := p.expr(token.lowest_prec) expr,typ := p.expr(0)
if _ := p.table.find_var(name) { if _ := p.table.find_var(name) {
p.error('redefinition of `$name`') p.error('redefinition of `$name`')
} }
@ -1101,6 +1136,29 @@ fn (p mut Parser) global_decl() ast.GlobalDecl {
} }
} }
fn (p mut Parser) match_expr() (ast.Expr,table.Type) {
p.check(.key_match)
p.expr(0)
p.check(.lcbr)
for {
// p.tok.kind != .rcbr {
p.expr(0)
p.warn('match block')
p.parse_block()
if p.tok.kind == .key_else {
p.next()
p.parse_block()
}
if p.tok.kind == .rcbr {
break
}
}
p.check(.rcbr)
mut node := ast.Expr{}
node = ast.MatchExpr{}
return node,table.void_type
}
fn (p mut Parser) add_unresolved(expr ast.Expr) table.Type { fn (p mut Parser) add_unresolved(expr ast.Expr) table.Type {
t := table.Type{ t := table.Type{
idx: p.unresolved.len idx: p.unresolved.len

View File

@ -388,7 +388,9 @@ pub fn (tok Token) precedence() int {
return 3 return 3
} }
// `||` // `||`
.logical_or, .assign, .plus_assign, .minus_assign, .div_assign, .mult_assign { .logical_or, .assign, .plus_assign, .minus_assign, .div_assign, .or_assign,
//
.left_shift_assign, .righ_shift_assign, .mult_assign {
return 2 return 2
} }
.key_in { .key_in {
@ -415,6 +417,7 @@ pub fn (tok Token) is_unary() bool {
.plus, .minus, .not, .bit_not, .mul, .amp] .plus, .minus, .not, .bit_not, .mul, .amp]
} }
/*
// NOTE: do we need this for all tokens (is_left_assoc / is_right_assoc), // NOTE: do we need this for all tokens (is_left_assoc / is_right_assoc),
// or only ones with the same precedence? // or only ones with the same precedence?
// is_left_assoc returns true if the token is left associative // is_left_assoc returns true if the token is left associative
@ -451,6 +454,8 @@ pub fn (tok Token) is_right_assoc() bool {
// `&=` | `^=` | `|=` // `&=` | `^=` | `|=`
.and_assign, .xor_assign, .or_assign] .and_assign, .xor_assign, .or_assign]
} }
*/
pub fn (tok Kind) is_relational() bool { pub fn (tok Kind) is_relational() bool {
return tok in [ return tok in [
@ -461,5 +466,5 @@ pub fn (tok Kind) is_relational() bool {
pub fn (kind Kind) is_infix() bool { pub fn (kind Kind) is_infix() bool {
return kind in [.plus, .minus, .mod, .mul, .div, .eq, .ne, .gt, .lt, .key_in, .ge, .le, .logical_or, return kind in [.plus, .minus, .mod, .mul, .div, .eq, .ne, .gt, .lt, .key_in, .ge, .le, .logical_or,
// //
.and, .dot, .pipe, .left_shift, .right_shift] .and, .dot, .pipe, .amp, .left_shift, .right_shift]
} }