mirror of
https://github.com/bearlanguageorg/bear.git
synced 2026-08-26 14:57:18 +00:00
stdlin
This commit is contained in:
@@ -421,6 +421,52 @@ fn (mut v Vm) json_encode_value(x i64, depth int) !string {
|
||||
return v.dec_int(x).str()
|
||||
}
|
||||
|
||||
// json_pretty_value renders a value as indented, multi-line JSON (the
|
||||
// `json_pretty` builtin used by the json stdlib module).
|
||||
fn (mut v Vm) json_pretty_value(x i64, depth int) !string {
|
||||
ind := ' '.repeat(depth)
|
||||
ind1 := ' '.repeat(depth + 1)
|
||||
if v.is_none(x) {
|
||||
return 'null'
|
||||
}
|
||||
if v.is_str(x) && v.valid_handle(x) {
|
||||
return json_quote(v.strings[v.hand(x)])
|
||||
}
|
||||
if v.is_arr(x) && v.valid_arr_handle(x) {
|
||||
a := v.arrays[v.hand(x)]
|
||||
if a.len == 0 {
|
||||
return '[]'
|
||||
}
|
||||
mut parts := []string{}
|
||||
for el in a {
|
||||
parts << ind1 + v.json_pretty_value(el, depth + 1)!
|
||||
}
|
||||
return '[\n' + parts.join(',\n') + '\n' + ind + ']'
|
||||
}
|
||||
if v.is_struct(x) && v.valid_struct_handle(x) {
|
||||
s := v.structs[v.hand(x)]
|
||||
if s.fields.len == 0 {
|
||||
return '{}'
|
||||
}
|
||||
mut parts := []string{}
|
||||
for f in s.fields {
|
||||
parts << ind1 + json_quote(f.name) + ': ' + v.json_pretty_value(f.val, depth + 1)!
|
||||
}
|
||||
return '{\n' + parts.join(',\n') + '\n' + ind + '}'
|
||||
}
|
||||
if v.is_float(x) && v.valid_float_handle(x) {
|
||||
f := v.fval(x)
|
||||
if math.is_nan(f) || math.is_inf(f, 1) || math.is_inf(f, -1) {
|
||||
return error('cannot encode NaN or Infinity as JSON')
|
||||
}
|
||||
return fmt_float(f)
|
||||
}
|
||||
if v.is_closure(x) && v.valid_closure_handle(x) {
|
||||
return error('cannot encode a function value as JSON')
|
||||
}
|
||||
return v.dec_int(x).str()
|
||||
}
|
||||
|
||||
// json_quote escapes a string into a JSON string literal. UTF-8 bytes pass
|
||||
// through untouched; control characters become \\u00XX escapes.
|
||||
fn json_quote(s string) string {
|
||||
|
||||
+12
@@ -513,6 +513,10 @@ fn (mut v Vm) native(id int, _argc int) ! {
|
||||
p := v.pop_str()!
|
||||
v.push(v.enc_int(bool_i64(os.exists(p))))!
|
||||
}
|
||||
native_build_is_dir {
|
||||
p := v.pop_str()!
|
||||
v.push(v.enc_int(bool_i64(os.is_dir(p))))!
|
||||
}
|
||||
native_build_mkdir {
|
||||
p := v.pop_str()!
|
||||
os.mkdir_all(p) or { return error('build_mkdir: cannot create ${p}: ${err.msg()}') }
|
||||
@@ -635,6 +639,14 @@ fn (mut v Vm) native(id int, _argc int) ! {
|
||||
}
|
||||
v.push(v.alloc_str(s.repeat(n)))!
|
||||
}
|
||||
native_cwd {
|
||||
v.push(v.alloc_str(os.getwd()))!
|
||||
}
|
||||
native_json_pretty {
|
||||
x := v.pop()!
|
||||
s := v.json_pretty_value(x, 0) or { return error('json_pretty: ${err.msg()}') }
|
||||
v.push(v.alloc_str(s))!
|
||||
}
|
||||
else {
|
||||
return error('unknown native builtin ${id}')
|
||||
}
|
||||
|
||||
@@ -137,3 +137,6 @@ const native_split_lines = 161
|
||||
const native_pad = 162
|
||||
const native_pad_left = 163
|
||||
const native_repeat = 164
|
||||
const native_build_is_dir = 165
|
||||
const native_cwd = 166
|
||||
const native_json_pretty = 167
|
||||
|
||||
@@ -239,20 +239,22 @@ fn (mut v Vm) exec() ! {
|
||||
}
|
||||
op_jmp {
|
||||
v.ip++
|
||||
v.ip = int(v.read_i64())
|
||||
// jump targets are PC-relative (delta from the end of the
|
||||
// operand), so merged/linked bytecode stays position-independent
|
||||
v.ip += int(v.read_i64())
|
||||
}
|
||||
op_jz {
|
||||
v.ip++
|
||||
target := int(v.read_i64())
|
||||
if !v.truthy(v.pop()!) {
|
||||
v.ip = target
|
||||
v.ip += target
|
||||
}
|
||||
}
|
||||
op_jnz {
|
||||
v.ip++
|
||||
target := int(v.read_i64())
|
||||
if v.truthy(v.pop()!) {
|
||||
v.ip = target
|
||||
v.ip += target
|
||||
}
|
||||
}
|
||||
op_call {
|
||||
@@ -499,7 +501,7 @@ fn (mut v Vm) exec() ! {
|
||||
}
|
||||
op_try {
|
||||
v.ip++
|
||||
catch_ip := int(v.read_i64())
|
||||
catch_ip := int(v.read_i64()) + v.ip
|
||||
v.handlers << Handler{ ip: catch_ip, bp: v.bp, sp: v.sp }
|
||||
}
|
||||
op_throw {
|
||||
@@ -536,15 +538,15 @@ fn (mut v Vm) exec() ! {
|
||||
return error('cannot call a non-function value')
|
||||
}
|
||||
entry := v.closures[v.hand(h)].entry
|
||||
// Shift args left to overwrite the closure slot, then
|
||||
// insert a return-value placeholder so the callee's
|
||||
// retv never overwrites the caller's local that held
|
||||
// the closure handle.
|
||||
// Shift args left to overwrite the closure slot (and drop the
|
||||
// duplicated tail), so the callee's retv lands exactly where the
|
||||
// call sequence began and no stale value is left below the
|
||||
// result. The caller's own local holding the closure sits below
|
||||
// the pushed sequence and is never touched.
|
||||
for i := 0; i < argc; i++ {
|
||||
v.stack[v.sp - argc - 1 + i] = v.stack[v.sp - argc + i]
|
||||
}
|
||||
v.stack[v.sp - 1] = v.enc_int(0) // return-value placeholder
|
||||
v.sp-- // closure was removed; unwind one slot
|
||||
v.sp-- // drop the duplicated arg tail; closure slot was consumed
|
||||
v.call(entry, argc)
|
||||
}
|
||||
op_argc {
|
||||
|
||||
Reference in New Issue
Block a user