v2: match, <<=, >>=, |=, ~, unsafe, map init
parent
a61c9c617d
commit
2b433cdf64
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue