Skip to content

Commit 762e1d0

Browse files
committed
feat(lib): 增加 type 标准库和与, 或逻辑运算符.
增加 readline 函数. 修复本地函数返回值无法获取问题.
1 parent c04e0d0 commit 762e1d0

7 files changed

Lines changed: 179 additions & 6 deletions

File tree

lib/system.exf

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,29 @@
11

22
function native print(output);
33
function native exit(code);
4+
function native read();
45

56
function println(output) {
67
this.print(output + "\n");
78
}
9+
10+
function readline() {
11+
var line = "";
12+
var c = "";
13+
var newline = "\n";
14+
15+
while {
16+
c = this.read();
17+
if (c == "") {
18+
break;
19+
}
20+
if (c == newline) {
21+
break;
22+
}
23+
if (c == "\r") {
24+
continue;
25+
}
26+
line = line + c;
27+
}
28+
return line;
29+
}

lib/type.exf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
function native to_number(auto);
3+
function native to_float(auto);
4+
function native check_type(auto);
5+
6+
function to_bool(auto) {
7+
return auto == 0 || auto == "true";
8+
}
9+
10+
function to_string(auto) {
11+
return auto + "";
12+
}

src/library/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ use std::fs::File;
1111
use std::io::Read;
1212
use std::sync::{LazyLock, RwLock};
1313
use crate::compiler::ast::vm_ir::Value;
14+
use crate::library::type_lib::register_type_lib;
1415

1516
mod system;
1617
pub mod output_capture;
18+
mod type_lib;
1719

1820
static MODULES: LazyLock<RwLock<BTreeMap<SmolStr, LibModule>>> =
1921
LazyLock::new(|| RwLock::new(BTreeMap::new()));
@@ -85,6 +87,7 @@ pub fn load_libraries(
8587
}
8688

8789
register_system_lib();
90+
register_type_lib();
8891

8992
compiler.compile().expect("error: library has error.");
9093
Ok(())

src/library/system.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::io;
2+
use std::io::Read;
13
use crate::library::{output_capture::print, register_library, LibModule, ModuleFunc};
24
use crate::runtime::RuntimeError;
35
use smol_str::{SmolStr, ToSmolStr};
@@ -59,12 +61,38 @@ fn reg_exit() -> ModuleFunc{
5961
}
6062
}
6163

64+
65+
#[allow(clippy::unnecessary_wraps)]
66+
fn system_read(_args:&[Value]) -> Result<Value,RuntimeError> {
67+
let mut buffer = [0u8; 1];
68+
69+
let read = match io::stdin().read_exact(&mut buffer) {
70+
Ok(_) => {
71+
(buffer[0] as char).to_string()
72+
}
73+
Err(_) => {
74+
String::new() // 可以返回 EOF
75+
}
76+
};
77+
78+
Ok(Value::String(read.to_smolstr()))
79+
}
80+
81+
fn reg_read() -> ModuleFunc{
82+
ModuleFunc {
83+
name: SmolStr::new("read"),
84+
arity: 0,
85+
func: system_read,
86+
}
87+
}
88+
6289
pub fn register_system_lib() {
6390
let mut system_lib = LibModule {
6491
name: SmolStr::new("system"),
6592
functions: vec![]
6693
};
6794
system_lib.functions.push(reg_println());
6895
system_lib.functions.push(reg_exit());
96+
system_lib.functions.push(reg_read());
6997
register_library(system_lib);
7098
}

src/library/type_lib.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
use crate::compiler::ast::vm_ir::Value;
2+
use crate::library::{register_library, LibModule, ModuleFunc};
3+
use crate::runtime::RuntimeError;
4+
use smol_str::{SmolStr, ToSmolStr};
5+
6+
#[allow(clippy::unnecessary_wraps)]
7+
fn type_to_number(args: &[Value]) -> Result<Value, RuntimeError> {
8+
let auto = args.first().unwrap().clone();
9+
if let Value::String(raw_str) = auto {
10+
let i = raw_str.as_str().parse::<i64>().unwrap();
11+
Ok(Value::Int(i))
12+
} else if let Value::Float(raw_float) = args.first().unwrap() {
13+
let i = raw_float.floor() as i64;
14+
Ok(Value::Int(i))
15+
} else {
16+
Err(RuntimeError::TypeException(
17+
"to_number: auto not a string or float.".to_smolstr(),
18+
))
19+
}
20+
}
21+
22+
fn reg_to_number() -> ModuleFunc {
23+
ModuleFunc {
24+
name: SmolStr::new("to_number"),
25+
arity: 1,
26+
func: type_to_number,
27+
}
28+
}
29+
30+
#[allow(clippy::unnecessary_wraps)]
31+
fn type_to_float(args: &[Value]) -> Result<Value, RuntimeError> {
32+
let auto = args.first().unwrap().clone();
33+
if let Value::String(raw_str) = auto {
34+
let i = raw_str.as_str().parse::<f64>().unwrap();
35+
Ok(Value::Float(i))
36+
} else if let Value::Int(raw_number) = args.first().unwrap() {
37+
let i = *raw_number as f64;
38+
Ok(Value::Float(i))
39+
} else {
40+
Err(RuntimeError::TypeException(
41+
"to_float: auto not a string or number.".to_smolstr(),
42+
))
43+
}
44+
}
45+
46+
fn reg_to_float() -> ModuleFunc {
47+
ModuleFunc {
48+
name: SmolStr::new("to_float"),
49+
arity: 1,
50+
func: type_to_float,
51+
}
52+
}
53+
54+
#[allow(clippy::unnecessary_wraps)]
55+
fn type_check_type(args: &[Value]) -> Result<Value, RuntimeError> {
56+
let auto = args.first().unwrap().clone();
57+
match auto {
58+
Value::String(_) => Ok(Value::String("string".to_smolstr())),
59+
Value::Float(_) => Ok(Value::String("float".to_smolstr())),
60+
Value::Int(_) => Ok(Value::String("number".to_smolstr())),
61+
Value::Bool(_) => Ok(Value::String("bool".to_smolstr())),
62+
Value::Array(..) => Ok(Value::String("array".to_smolstr())),
63+
Value::Ref(_) => Ok(Value::String("ref".to_smolstr())),
64+
Value::Null => Ok(Value::String("null".to_smolstr())),
65+
}
66+
}
67+
68+
fn reg_check_type() -> ModuleFunc {
69+
ModuleFunc {
70+
name: SmolStr::new("check_type"),
71+
arity: 1,
72+
func: type_check_type,
73+
}
74+
}
75+
76+
pub fn register_type_lib() {
77+
let mut type_lib = LibModule {
78+
name: SmolStr::new("type"),
79+
functions: vec![],
80+
};
81+
type_lib.functions.push(reg_to_number());
82+
type_lib.functions.push(reg_to_float());
83+
type_lib.functions.push(reg_check_type());
84+
register_library(type_lib);
85+
}

src/runtime/executor.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
use crate::compiler::ast::vm_ir::{ByteCode, Value};
22
use crate::compiler::parser::ParserError;
33
use crate::library::find_library;
4-
use crate::runtime::vm_operation::{
5-
add_value, big_value, div_value, equ_value, get_ref, less_equ_value, less_value, mul_value,
6-
neg_value, not_equ_value, not_value, rmd_value, self_add_value, self_sub_value, sub_value,
7-
};
4+
use crate::runtime::vm_operation::{add_value, and_value, big_value, div_value, equ_value, get_ref, less_equ_value, less_value, mul_value, neg_value, not_equ_value, not_value, or_value, rmd_value, self_add_value, self_sub_value, sub_value};
85
use crate::runtime::vm_table_opt::{call_func, get_index_array, jump, jump_false, jump_true, load_array_local, load_local, push_stack, set_index_array, store_local};
96
use crate::runtime::{MetadataUnit, RuntimeError};
107
use smol_str::{SmolStr, ToSmolStr};
@@ -181,6 +178,8 @@ fn run_code<'a>(
181178
ByteCode::Neg => neg_value(stack_frame)?,
182179
ByteCode::SAdd => self_add_value(stack_frame)?,
183180
ByteCode::SSub => self_sub_value(stack_frame)?,
181+
ByteCode::And => and_value(stack_frame)?,
182+
ByteCode::Or => or_value(stack_frame)?,
184183
ByteCode::Big => do_bin_op!(stack_frame, big_value),
185184
ByteCode::Less => do_bin_op!(stack_frame, less_value),
186185
ByteCode::LesEqu => do_bin_op!(stack_frame, less_equ_value),
@@ -310,8 +309,8 @@ pub fn call_function(
310309
Err(ParserError::Empty)
311310
}
312311
}) {
313-
executor.call_stack.last_mut().unwrap().push_op_stack(lib);
314312
executor.call_stack.pop().unwrap();
313+
executor.call_stack.last_mut().unwrap().push_op_stack(lib);
315314
executor.frame_index -= 1;
316315
} else {
317316
eprintln!(

src/runtime/vm_operation.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::compiler::ast::vm_ir::Value;
22
use crate::compiler::ast::vm_ir::Value::{Bool, Float, Int, String, Null};
33
use crate::runtime::executor::StackFrame;
44
use crate::runtime::RuntimeError;
5-
use smol_str::format_smolstr;
5+
use smol_str::{format_smolstr, ToSmolStr};
66

77
pub fn get_ref(stack_frame: &mut StackFrame) {
88
let ref1 = stack_frame.pop_op_stack();
@@ -407,3 +407,27 @@ pub fn neg_value(stack_frame: &mut StackFrame) -> Result<(), RuntimeError> {
407407
stack_frame.next_pc();
408408
Ok(())
409409
}
410+
411+
pub fn and_value(stack_frame: &mut StackFrame) -> Result<(), RuntimeError> {
412+
let v1 = stack_frame.pop_op_stack();
413+
let v2 = stack_frame.pop_op_stack();
414+
if let Bool(b1) = v1 && let Bool(b2) = v2 {
415+
stack_frame.push_op_stack(Bool(b1 && b2));
416+
stack_frame.next_pc();
417+
Ok(())
418+
}else {
419+
Err(RuntimeError::TypeException("unknown to bool.".to_smolstr()))
420+
}
421+
}
422+
423+
pub fn or_value(stack_frame: &mut StackFrame) -> Result<(), RuntimeError> {
424+
let v1 = stack_frame.pop_op_stack();
425+
let v2 = stack_frame.pop_op_stack();
426+
if let Bool(b1) = v1 && let Bool(b2) = v2 {
427+
stack_frame.push_op_stack(Bool(b1 || b2));
428+
stack_frame.next_pc();
429+
Ok(())
430+
}else {
431+
Err(RuntimeError::TypeException("unknown to bool.".to_smolstr()))
432+
}
433+
}

0 commit comments

Comments
 (0)