mirror of
https://github.com/bearlanguageorg/bear.git
synced 2026-08-26 14:57:18 +00:00
Added default json, etc.
This commit is contained in:
@@ -6,6 +6,7 @@ pub enum ExprKind {
|
||||
float_lit
|
||||
str_lit
|
||||
bool_lit
|
||||
none_lit
|
||||
ident
|
||||
array_lit
|
||||
struct_lit
|
||||
|
||||
+17
-8
@@ -18,6 +18,7 @@ enum CType {
|
||||
float_t
|
||||
string_t
|
||||
bool_t
|
||||
none_t
|
||||
array_t
|
||||
struct_t
|
||||
enum_t
|
||||
@@ -221,7 +222,7 @@ fn (mut c Checker) check_stmt(st Stmt) ! {
|
||||
.for_in_stmt {
|
||||
seq := c.check_expr(st.expr)!
|
||||
// iterate enums and arrays; unknown is allowed (dynamic)
|
||||
if seq.kind == .int_t || seq.kind == .float_t || seq.kind == .bool_t {
|
||||
if seq.kind == .int_t || seq.kind == .float_t || seq.kind == .bool_t || seq.kind == .none_t {
|
||||
return error('cannot iterate a ${type_name(seq.kind)} (line ${st.line})')
|
||||
}
|
||||
c.types[st.target] = TypeInfo{ kind: .unknown }
|
||||
@@ -271,6 +272,7 @@ fn (mut c Checker) check_expr(e Expr) !TypeInfo {
|
||||
.float_lit { TypeInfo{ kind: .float_t } }
|
||||
.str_lit { TypeInfo{ kind: .string_t } }
|
||||
.bool_lit { TypeInfo{ kind: .bool_t } }
|
||||
.none_lit { TypeInfo{ kind: .none_t } }
|
||||
.ident {
|
||||
if e.name in c.types {
|
||||
c.types[e.name]
|
||||
@@ -324,7 +326,7 @@ fn (mut c Checker) check_expr(e Expr) !TypeInfo {
|
||||
}
|
||||
.method_call {
|
||||
recv := c.check_expr(*e.left)!
|
||||
if recv.kind == .int_t || recv.kind == .float_t || recv.kind == .bool_t {
|
||||
if recv.kind == .int_t || recv.kind == .float_t || recv.kind == .bool_t || recv.kind == .none_t {
|
||||
return error('cannot call a method on a ${type_name(recv.kind)} (line ${e.line})')
|
||||
}
|
||||
for a in e.args {
|
||||
@@ -336,7 +338,7 @@ fn (mut c Checker) check_expr(e Expr) !TypeInfo {
|
||||
base := c.check_expr(*e.left)!
|
||||
_ = c.check_expr(*e.right)!
|
||||
_ = c.check_expr(*e.extra)!
|
||||
if base.kind == .int_t || base.kind == .float_t || base.kind == .bool_t {
|
||||
if base.kind == .int_t || base.kind == .float_t || base.kind == .bool_t || base.kind == .none_t {
|
||||
return error('cannot slice a ${type_name(base.kind)} (line ${e.line})')
|
||||
}
|
||||
if base.kind == .string_t {
|
||||
@@ -424,6 +426,9 @@ fn (mut c Checker) check_binary(e Expr) !TypeInfo {
|
||||
if l.kind == .bool_t && r.kind == .bool_t {
|
||||
return error('cannot order booleans (line ${e.line})')
|
||||
}
|
||||
if l.kind == .none_t || r.kind == .none_t {
|
||||
return error('cannot order a none (line ${e.line})')
|
||||
}
|
||||
if l.kind != .unknown && r.kind != .unknown && l.kind != r.kind && !(is_num_kind(l.kind) && is_num_kind(r.kind)) {
|
||||
return error('cannot compare a ${type_name(l.kind)} and a ${type_name(r.kind)} (line ${e.line})')
|
||||
}
|
||||
@@ -450,7 +455,7 @@ fn (mut c Checker) check_call(e Expr) !TypeInfo {
|
||||
return error('len() takes exactly one argument (line ${e.line})')
|
||||
}
|
||||
t := c.check_expr(e.args[0])!
|
||||
if t.kind == .int_t || t.kind == .float_t || t.kind == .bool_t || t.kind == .closure_t {
|
||||
if t.kind == .int_t || t.kind == .float_t || t.kind == .bool_t || t.kind == .none_t || t.kind == .closure_t {
|
||||
return error('len() on a ${type_name(t.kind)} (line ${e.line})')
|
||||
}
|
||||
return TypeInfo{ kind: .int_t }
|
||||
@@ -552,6 +557,9 @@ fn builtin_result_type(name string) TypeInfo {
|
||||
'args', 'keys' { TypeInfo{ kind: .array_t } }
|
||||
'len' { TypeInfo{ kind: .int_t } }
|
||||
'write_file', 'setenv', 'exit', 'sleep', 'eprint' { TypeInfo{ kind: .unknown } }
|
||||
// stdlib: JSON + string formatting
|
||||
'json_encode', 'format', 'replace', 'pad', 'pad_left', 'repeat' { TypeInfo{ kind: .string_t } }
|
||||
'json_decode', 'split_lines' { TypeInfo{ kind: .unknown } }
|
||||
// build-module builtins (.vrmm)
|
||||
'build_compile', 'build_assemble', 'build_link', 'build_exec', 'build_base',
|
||||
'build_dir', 'build_join', 'build_root' { TypeInfo{ kind: .string_t } }
|
||||
@@ -576,30 +584,31 @@ fn type_name(k CType) string {
|
||||
.struct_t { 'struct' }
|
||||
.enum_t { 'enum' }
|
||||
.closure_t { 'function' }
|
||||
.none_t { 'none' }
|
||||
else { 'value' }
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Checker) expect_numeric(t TypeInfo, what string, line int) ! {
|
||||
if t.kind == .string_t || t.kind == .array_t || t.kind == .struct_t || t.kind == .bool_t || t.kind == .closure_t {
|
||||
if t.kind == .string_t || t.kind == .array_t || t.kind == .struct_t || t.kind == .bool_t || t.kind == .none_t || t.kind == .closure_t {
|
||||
return error('${what} on a ${type_name(t.kind)} (line ${line})')
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Checker) expect_int(t TypeInfo, what string, line int) ! {
|
||||
if t.kind == .string_t || t.kind == .array_t || t.kind == .struct_t || t.kind == .bool_t || t.kind == .closure_t || t.kind == .float_t {
|
||||
if t.kind == .string_t || t.kind == .array_t || t.kind == .struct_t || t.kind == .bool_t || t.kind == .none_t || t.kind == .closure_t || t.kind == .float_t {
|
||||
return error('${what} requires an int, got a ${type_name(t.kind)} (line ${line})')
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Checker) expect_container(t TypeInfo, what string, line int) ! {
|
||||
if t.kind == .int_t || t.kind == .float_t || t.kind == .bool_t || t.kind == .closure_t {
|
||||
if t.kind == .int_t || t.kind == .float_t || t.kind == .bool_t || t.kind == .none_t || t.kind == .closure_t {
|
||||
return error('${what} on a ${type_name(t.kind)} (line ${line})')
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut c Checker) expect_struct_like(t TypeInfo, what string, line int) ! {
|
||||
if t.kind == .int_t || t.kind == .float_t || t.kind == .bool_t || t.kind == .string_t || t.kind == .closure_t {
|
||||
if t.kind == .int_t || t.kind == .float_t || t.kind == .bool_t || t.kind == .string_t || t.kind == .none_t || t.kind == .closure_t {
|
||||
return error('${what} on a ${type_name(t.kind)} (line ${line})')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -723,6 +723,9 @@ fn (mut g Gen) gen_expr(e Expr) ! {
|
||||
g.code << op_push_i
|
||||
g.code << obj.encode_i64(e.int_v)
|
||||
}
|
||||
.none_lit {
|
||||
g.code << op_push_none
|
||||
}
|
||||
.ident {
|
||||
// check if it's a constant
|
||||
if e.name in g.consts {
|
||||
@@ -923,6 +926,15 @@ fn builtin_spec(name string) (int, int) {
|
||||
'build_dir' { native_build_dir, 1 }
|
||||
'build_join' { native_build_join, 2 }
|
||||
'build_root' { native_build_root, 0 }
|
||||
// stdlib: JSON + string formatting
|
||||
'json_encode' { native_json_encode, 1 }
|
||||
'json_decode' { native_json_decode, 1 }
|
||||
'format' { native_format, 2 }
|
||||
'replace' { native_replace, 3 }
|
||||
'split_lines' { native_split_lines, 1 }
|
||||
'pad' { native_pad, 2 }
|
||||
'pad_left' { native_pad_left, 2 }
|
||||
'repeat' { native_repeat, 2 }
|
||||
else { -1, 0 }
|
||||
}
|
||||
}
|
||||
@@ -1153,6 +1165,7 @@ fn (mut g Gen) expr_type(e Expr) string {
|
||||
'upper', 'lower', 'trim', 'str', 'getenv', 'read_file', 'join' { 'string' }
|
||||
'build_compile', 'build_assemble', 'build_link', 'build_exec', 'build_base',
|
||||
'build_dir', 'build_join', 'build_root' { 'string' }
|
||||
'json_encode', 'format', 'replace', 'pad', 'pad_left', 'repeat' { 'string' }
|
||||
else { '' }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,6 +291,7 @@ fn (mut l Lexer) lex_ident(line int, col int) Tok {
|
||||
'return' { TokKind.kw_return }
|
||||
'true' { TokKind.kw_true }
|
||||
'false' { TokKind.kw_false }
|
||||
'none' { TokKind.kw_none }
|
||||
'and' { TokKind.kw_and }
|
||||
'or' { TokKind.kw_or }
|
||||
'not' { TokKind.kw_not }
|
||||
|
||||
@@ -65,6 +65,7 @@ const op_argc = u8(58) // push the current frame's arg count
|
||||
const op_load_dyn = u8(59) // pop idx, push stack[bp + idx]
|
||||
const op_varargs = u8(60) // <named:i64> <dst:i64> — collect args[named..argc-1] into an array at local dst
|
||||
const op_str_method = u8(61) // <name:str> <argc:i64> — call a string method (s.len(), s.contains(x), ...)
|
||||
const op_push_none = u8(62) // push the `none` sentinel
|
||||
|
||||
// native builtin ids (keep in sync with vm/opcodes.v)
|
||||
const native_abs = 100
|
||||
@@ -127,3 +128,13 @@ const native_build_base = 153
|
||||
const native_build_dir = 154
|
||||
const native_build_join = 155
|
||||
const native_build_root = 156
|
||||
|
||||
// stdlib builtins (JSON + string formatting)
|
||||
const native_json_encode = 157
|
||||
const native_json_decode = 158
|
||||
const native_format = 159
|
||||
const native_replace = 160
|
||||
const native_split_lines = 161
|
||||
const native_pad = 162
|
||||
const native_pad_left = 163
|
||||
const native_repeat = 164
|
||||
|
||||
@@ -787,6 +787,10 @@ fn (mut p Parser) parse_primary() !Expr {
|
||||
p.advance()
|
||||
return Expr{ kind: .bool_lit, int_v: 0, line: t.line }
|
||||
}
|
||||
.kw_none {
|
||||
p.advance()
|
||||
return Expr{ kind: .none_lit, line: t.line }
|
||||
}
|
||||
.lparen {
|
||||
p.advance()
|
||||
e := p.parse_expr()!
|
||||
|
||||
@@ -55,6 +55,7 @@ pub enum TokKind {
|
||||
kw_return
|
||||
kw_true
|
||||
kw_false
|
||||
kw_none
|
||||
kw_and
|
||||
kw_or
|
||||
kw_not
|
||||
|
||||
Reference in New Issue
Block a user