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 }
hex := malloc(len)
// QTODO
count := C.sprintf(charptr(hex), '0x%'C.PRIx64, n)
//count := C.sprintf(charptr(hex), '0x%x', n)
//count := C.sprintf(charptr(hex), '0x%'C.PRIx64, n)
count := C.sprintf(charptr(hex), '0x%x', n)
return tos(hex, count)
}
pub fn (n u64) hex() string {
len := if n >= u64(0) { n.str().len + 3 } else { 19 }
hex := malloc(len)
count := C.sprintf(charptr(hex), '0x%'C.PRIx64, n)
//count := C.sprintf(charptr(hex), '0x%lx', n)
//count := C.sprintf(charptr(hex), '0x%'C.PRIx64, n)
count := C.sprintf(charptr(hex), '0x%lx', n)
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 {
_ = s.index(p) or {
s.index(p) or {
return false
}
return true

View File

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

View File

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

View File

@ -10,7 +10,7 @@ import (
pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral |
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 |
ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt |
@ -275,6 +275,17 @@ pub:
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:
cond Expr

View File

@ -16,12 +16,14 @@ import (
const (
colored_output = term.can_show_color_on_stderr()
)
/*
type PrefixParseFn fn()ast.Expr
type InfixParseFn fn(e ast.Expr)ast.Expr
type PostfixParseFn fn()ast.Expr
*/
struct Parser {
scanner &scanner.Scanner
@ -232,9 +234,14 @@ pub fn (p mut Parser) stmt() ast.Stmt {
tok: p.tok
}
}
.key_unsafe {
p.next()
p.parse_block()
return ast.Stmt{}
}
else {
// `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()
}
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 {
// ,table.Type) {
if p.tok.kind != .dotdot {
p.next()
}
p.check(.dotdot)
high,typ := p.expr(0)
if typ.kind != .int {
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.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
if p.peek_tok.kind == .lpar {
println('calling $p.tok.lit')
@ -380,7 +401,8 @@ pub fn (p mut Parser) name_expr() (ast.Expr,table.Type) {
typ = ti2
}
// 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()
// p.warn('struct init typ=$typ.name')
p.check(.lcbr)
@ -476,8 +498,8 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
}
p.next()
}
// -1, -a, !x, &x etc
.minus, .amp, .mul, .not {
// -1, -a, !x, &x, ~x
.minus, .amp, .mul, .not, .bit_not {
node,typ = p.prefix_expr()
}
// .amp {
@ -490,6 +512,9 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
typ = table.bool_type
p.next()
}
.key_match {
return p.match_expr()
}
.number {
node,typ = p.parse_number_literal()
}
@ -504,6 +529,9 @@ pub fn (p mut Parser) expr(precedence int) (ast.Expr,table.Type) {
.lsbr {
node,typ = p.array_init()
}
.key_none {
p.next()
}
.key_sizeof {
p.next()
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')
p.next() // [
mut index_expr := ast.Expr{}
if p.tok.kind == .dotdot {
if p.tok.kind == .dotdot || p.peek_tok.kind == .dotdot {
// `numbers[..end]`
index_expr = p.range_expr(left)
// 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 left := ast.Expr{}
// If the last statement is an expression, return its type
if stmts.len > 0 {
match stmts[stmts.len - 1] {
ast.ExprStmt {
p.warn('if expr ret $it.ti.name')
@ -776,6 +805,7 @@ fn (p mut Parser) if_expr() (ast.Expr,table.Type) {
}
else {}
}
}
node = ast.IfExpr{
cond: cond
stmts: stmts
@ -958,6 +988,11 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
field_name := p.check_name()
// p.warn('field $field_name')
ti := p.parse_type()
// Default value
if p.tok.kind == .assign {
p.next()
p.expr(0)
}
ast_fields << ast.Field{
name: field_name
typ: ti
@ -1034,9 +1069,9 @@ fn (p mut Parser) var_decl() ast.VarDecl {
p.check(.key_static)
// p.fspace()
}
name := p.tok.lit
p.read_first_token()
expr,typ := p.expr(token.lowest_prec)
name := p.check_name()
p.next()
expr,typ := p.expr(0)
if _ := p.table.find_var(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 {
t := table.Type{
idx: p.unresolved.len

View File

@ -388,7 +388,9 @@ pub fn (tok Token) precedence() int {
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
}
.key_in {
@ -415,6 +417,7 @@ pub fn (tok Token) is_unary() bool {
.plus, .minus, .not, .bit_not, .mul, .amp]
}
/*
// NOTE: do we need this for all tokens (is_left_assoc / is_right_assoc),
// or only ones with the same precedence?
// 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]
}
*/
pub fn (tok Kind) is_relational() bool {
return tok in [
@ -461,5 +466,5 @@ pub fn (tok Kind) is_relational() 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,
//
.and, .dot, .pipe, .left_shift, .right_shift]
.and, .dot, .pipe, .amp, .left_shift, .right_shift]
}