Tracing options, while loop
This commit is contained in:
+17
-15
@@ -7,18 +7,20 @@
|
||||
)
|
||||
)
|
||||
|
||||
(print 1 "\t" (factorial 1))
|
||||
(print 2 "\t" (factorial 2))
|
||||
(print 3 "\t" (factorial 3))
|
||||
(print 4 "\t" (factorial 4))
|
||||
(print 5 "\t" (factorial 5))
|
||||
(print 6 "\t" (factorial 6))
|
||||
(print 7 "\t" (factorial 7))
|
||||
(print 8 "\t" (factorial 8))
|
||||
(print 9 "\t" (factorial 9))
|
||||
(print 10 "\t" (factorial 10))
|
||||
(print 11 "\t" (factorial 11))
|
||||
(print 12 "\t" (factorial 12))
|
||||
(print 13 "\t" (factorial 13))
|
||||
(print 14 "\t" (factorial 14))
|
||||
(print 15 "\t" (factorial 15))
|
||||
(defun loop-factorial (x)
|
||||
(let (i 0 acc 1)
|
||||
(while (< i x)
|
||||
(setq i (+ i 1))
|
||||
(setq acc (* acc i))
|
||||
)
|
||||
acc
|
||||
)
|
||||
)
|
||||
|
||||
;; TODO for loops?
|
||||
(let (i 0)
|
||||
(while (<= i 15)
|
||||
(print i "\t" (factorial i) "\t" (loop-factorial i))
|
||||
(setq i (+ i 1))
|
||||
)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
;; vi:ft=lisp:sw=2:ts=2
|
||||
|
||||
(defun replace-argument (x) (let (x 1) x))
|
||||
|
||||
(defun replace-let ()
|
||||
(let (x 1)
|
||||
(setq x 2) ;; mutate local x
|
||||
x
|
||||
)
|
||||
)
|
||||
|
||||
(defun reassignment-in-a-loop (iterations)
|
||||
(let (x 0 y 1)
|
||||
(while (< x iterations)
|
||||
(setq y (* y 2))
|
||||
(setq x (+ x 1))
|
||||
)
|
||||
y
|
||||
)
|
||||
)
|
||||
|
||||
(assert (= (replace-argument 2) 1))
|
||||
(assert (= (replace-argument 3) 1))
|
||||
(assert (= (replace-let) 2))
|
||||
(assert (= (reassignment-in-a-loop 4) 16))
|
||||
+63
-15
@@ -9,6 +9,7 @@ use crate::{
|
||||
syntax::{
|
||||
CallExpression, CondExpression, DefmacroExpression, DefunExpression, Expression,
|
||||
FunctionBody, IfExpression, LambdaExpression, LetExpression, SetqExpression,
|
||||
WhileExpression,
|
||||
},
|
||||
value::{BuiltinFunction, CompileConstant, CompileValue},
|
||||
},
|
||||
@@ -136,13 +137,19 @@ impl FunctionBlock {
|
||||
self.labels.insert(label, self.instructions.len());
|
||||
}
|
||||
|
||||
pub fn resolve_labels(self) -> CompiledFunction {
|
||||
pub fn resolve_labels(self, trace: bool) -> CompiledFunction {
|
||||
let mut instructions = vec![];
|
||||
// eprintln!("RESOLVE LABELS");
|
||||
|
||||
if trace {
|
||||
eprintln!("Instruction resolution:");
|
||||
}
|
||||
|
||||
for (function_offset, emitted) in self.instructions.into_iter().enumerate() {
|
||||
match emitted {
|
||||
Emitted::Instruction(instruction) => {
|
||||
// eprintln!("{function_offset}: {instruction:?}");
|
||||
if trace {
|
||||
eprintln!("{function_offset}: {instruction:?}");
|
||||
}
|
||||
instructions.push(instruction);
|
||||
}
|
||||
Emitted::Branch(label) => {
|
||||
@@ -151,9 +158,11 @@ impl FunctionBlock {
|
||||
todo!()
|
||||
}
|
||||
let diff = address.checked_signed_diff(function_offset).expect("TODO");
|
||||
// eprintln!(
|
||||
// "{function_offset}: branch to label {label} (@ {address}) -> {diff:+}"
|
||||
// );
|
||||
if trace {
|
||||
eprintln!(
|
||||
"{function_offset}: Branch: label {label} (@ {address}) -> {diff:+}"
|
||||
);
|
||||
}
|
||||
let offset = U::from_signed(diff as i64).expect("TODO");
|
||||
instructions.push(Instruction::Branch(offset));
|
||||
}
|
||||
@@ -163,7 +172,11 @@ impl FunctionBlock {
|
||||
todo!()
|
||||
}
|
||||
let diff = address.checked_signed_diff(function_offset).expect("TODO");
|
||||
// eprintln!("{function_offset}: jump to label {label} (@ {address}) -> {diff:+}");
|
||||
if trace {
|
||||
eprintln!(
|
||||
"{function_offset}: jump to label {label} (@ {address}) -> {diff:+}"
|
||||
);
|
||||
}
|
||||
let offset = U::from_signed(diff as i64).expect("TODO");
|
||||
instructions.push(Instruction::Jump(offset));
|
||||
}
|
||||
@@ -464,6 +477,30 @@ impl<'a> LocalBlock<'a> {
|
||||
Ok(CompileValue::Stack)
|
||||
}
|
||||
|
||||
fn compile_while(&mut self, cloop: &WhileExpression) -> Result<CompileValue, CompileError> {
|
||||
let label_start = self.function.new_label();
|
||||
let label_end = self.function.new_label();
|
||||
|
||||
self.function.adjust_label(label_start);
|
||||
|
||||
// Condition
|
||||
let condition_value = self.compile_expression(&cloop.condition)?;
|
||||
self.compile_push(condition_value)?;
|
||||
self.function.emit(Emitted::Branch(label_end));
|
||||
|
||||
// Body
|
||||
for expression in &cloop.body.head {
|
||||
self.compile_statement(expression)?;
|
||||
}
|
||||
self.compile_statement(&cloop.body.tail)?;
|
||||
|
||||
// Jump back
|
||||
self.function.emit(Emitted::Jump(label_start));
|
||||
|
||||
self.function.adjust_label(label_end);
|
||||
Ok(CompileValue::Nil)
|
||||
}
|
||||
|
||||
fn compile_let(&mut self, binding: &LetExpression) -> Result<CompileValue, CompileError> {
|
||||
self.function.push_local_scope();
|
||||
let mut indices = vec![];
|
||||
@@ -496,7 +533,16 @@ impl<'a> LocalBlock<'a> {
|
||||
fn compile_setq(&mut self, setq: &SetqExpression) -> Result<CompileValue, CompileError> {
|
||||
for pair in setq.pairs.iter() {
|
||||
let value = self.compile_expression(&pair.value)?;
|
||||
self.compile_set_global(&pair.identifier, value)?;
|
||||
if let Some(index) = self
|
||||
.function
|
||||
.local_scope_ref()
|
||||
.and_then(|scope| scope.get(&pair.identifier))
|
||||
{
|
||||
self.compile_push(value)?;
|
||||
self.function.emit(Instruction::SetLocal(index));
|
||||
} else {
|
||||
self.compile_set_global(&pair.identifier, value)?;
|
||||
}
|
||||
}
|
||||
Ok(CompileValue::Nil)
|
||||
}
|
||||
@@ -524,6 +570,7 @@ impl<'a> LocalBlock<'a> {
|
||||
Expression::Setq(setq) => self.compile_setq(setq),
|
||||
Expression::Defmacro(defmacro) => self.compile_defmacro(defmacro),
|
||||
Expression::Quote(quote) => self.compile_quote(quote),
|
||||
Expression::While(cloop) => self.compile_while(cloop),
|
||||
|
||||
Expression::SyntaxError(_) => unreachable!(),
|
||||
}
|
||||
@@ -600,7 +647,8 @@ mod tests {
|
||||
};
|
||||
let mut local = LocalBlock::root(&mut function, &mut module);
|
||||
let value = local.compile_expression(&Rc::new(expression)).unwrap();
|
||||
(module, function.resolve_labels(), value)
|
||||
let trace = module.options.trace_compile;
|
||||
(module, function.resolve_labels(trace), value)
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -647,9 +695,9 @@ mod tests {
|
||||
&f.instructions,
|
||||
&[
|
||||
Instruction::PushBool(false), // 0
|
||||
Instruction::Branch(U::truncate(4)), // 1
|
||||
Instruction::Branch(U::truncate(3)), // 1
|
||||
Instruction::PushInteger(U::truncate(1)), // 2
|
||||
Instruction::Jump(U::truncate(5)), // 3
|
||||
Instruction::Jump(U::truncate(2)), // 3
|
||||
Instruction::PushInteger(U::truncate(2)) // 4
|
||||
// 5
|
||||
]
|
||||
@@ -676,13 +724,13 @@ mod tests {
|
||||
&f.instructions,
|
||||
&[
|
||||
Instruction::PushBool(false), // 0
|
||||
Instruction::Branch(U::truncate(4)), // 1
|
||||
Instruction::Branch(U::truncate(3)), // 1
|
||||
Instruction::PushInteger(U::truncate(1)), // 2
|
||||
Instruction::Jump(U::truncate(9)), // 3
|
||||
Instruction::Jump(U::truncate(6)), // 3
|
||||
Instruction::PushBool(true), // 4
|
||||
Instruction::Branch(U::truncate(8)), // 5
|
||||
Instruction::Branch(U::truncate(3)), // 5
|
||||
Instruction::PushInteger(U::truncate(2)), // 6
|
||||
Instruction::Jump(U::truncate(9)), // 7
|
||||
Instruction::Jump(U::truncate(2)), // 7
|
||||
Instruction::PushInteger(U::truncate(3)), // 8
|
||||
// 9
|
||||
]
|
||||
|
||||
@@ -13,3 +13,8 @@ pub use syntax::{
|
||||
CallExpression, ExpectedWhat, ExpectedWhere, Expression, FunctionBody, LambdaExpression,
|
||||
ParseError, ParseErrorKind,
|
||||
};
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct CompileOptions {
|
||||
pub trace_compile: bool,
|
||||
}
|
||||
|
||||
+10
-1
@@ -2,6 +2,7 @@ use std::{collections::HashMap, rc::Rc};
|
||||
|
||||
use crate::{
|
||||
compile::{
|
||||
CompileOptions,
|
||||
block::{CompiledFunction, FunctionBlock},
|
||||
error::CompileError,
|
||||
function::FunctionSignature,
|
||||
@@ -19,12 +20,20 @@ use crate::{
|
||||
pub struct CompilationModule {
|
||||
pub(crate) constant_pool: Pool<CompileConstant, { ConstantId::BITS }>,
|
||||
pub(crate) local_functions: HashMap<u32, CompiledFunction>,
|
||||
pub(crate) options: CompileOptions,
|
||||
macros: HashMap<Rc<str>, DefmacroExpression>,
|
||||
local_function_index: u32,
|
||||
root: Option<u32>,
|
||||
}
|
||||
|
||||
impl CompilationModule {
|
||||
pub fn new(options: CompileOptions) -> Self {
|
||||
Self {
|
||||
options,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn define_macro(&mut self, defmacro: DefmacroExpression) {
|
||||
self.macros.insert(defmacro.name.clone(), defmacro);
|
||||
}
|
||||
@@ -49,7 +58,7 @@ impl CompilationModule {
|
||||
self.local_function_index += 1;
|
||||
let mut function = FunctionBlock::new(signature);
|
||||
function.compile_body(self, body)?;
|
||||
let function = function.resolve_labels();
|
||||
let function = function.resolve_labels(self.options.trace_compile);
|
||||
self.local_functions.insert(index, function);
|
||||
if root {
|
||||
self.root = Some(index);
|
||||
|
||||
@@ -64,9 +64,9 @@ impl IfExpression {
|
||||
Some(Expression::parse_inner(if_false))
|
||||
};
|
||||
Ok(Self {
|
||||
condition: condition.into(),
|
||||
if_true: if_true.into(),
|
||||
if_false: if_false.map(Into::into),
|
||||
condition,
|
||||
if_true,
|
||||
if_false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::{
|
||||
compile::{
|
||||
ExpectedWhat, ExpectedWhere, Expression, FunctionBody, ParseError, ParseErrorKind,
|
||||
syntax::CollectErrors,
|
||||
},
|
||||
vm::value::{ConsCell, Keyword, Value},
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct WhileExpression {
|
||||
pub condition: Rc<Expression>,
|
||||
pub body: FunctionBody,
|
||||
}
|
||||
|
||||
impl WhileExpression {
|
||||
pub(super) fn parse(value: &Value, input: &Value) -> Result<Self, ParseError> {
|
||||
let Value::Cons(cons) = value else {
|
||||
return Err(ParseError {
|
||||
input: input.clone(),
|
||||
error: ParseErrorKind::Expected(
|
||||
ExpectedWhat::ProperList,
|
||||
ExpectedWhere::AfterKeyword(Keyword::While),
|
||||
),
|
||||
});
|
||||
};
|
||||
let ConsCell(car, cdr) = cons.as_ref();
|
||||
let condition = Expression::parse_inner(car);
|
||||
let body = FunctionBody::parse(cdr, input, Keyword::While)?;
|
||||
Ok(Self { condition, body })
|
||||
}
|
||||
}
|
||||
|
||||
impl CollectErrors<ParseError> for WhileExpression {
|
||||
fn collect_errors(&self, errors: &mut Vec<ParseError>) -> bool {
|
||||
let a = self.condition.collect_errors(errors);
|
||||
let b = self.body.collect_errors(errors);
|
||||
a | b
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ mod condition;
|
||||
mod error;
|
||||
mod function;
|
||||
mod lambda;
|
||||
mod loops;
|
||||
mod macros;
|
||||
|
||||
pub use binding::*;
|
||||
@@ -16,6 +17,7 @@ pub use condition::*;
|
||||
pub use error::*;
|
||||
pub use function::*;
|
||||
pub use lambda::*;
|
||||
pub use loops::*;
|
||||
pub use macros::*;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@@ -35,6 +37,7 @@ pub enum Expression {
|
||||
Defmacro(DefmacroExpression),
|
||||
SyntaxError(ParseError),
|
||||
Quote(Rc<Value>),
|
||||
While(WhileExpression),
|
||||
}
|
||||
|
||||
impl Expression {
|
||||
@@ -97,6 +100,9 @@ impl Expression {
|
||||
};
|
||||
Rc::new(Self::Quote(value.into()))
|
||||
}
|
||||
Value::Keyword(Keyword::While) => {
|
||||
Self::map_or(WhileExpression::parse(cdr, value), Expression::While)
|
||||
}
|
||||
_ => Self::map_or(CallExpression::parse(cons, value), Expression::Call),
|
||||
}
|
||||
}
|
||||
@@ -123,6 +129,7 @@ impl CollectErrors<ParseError> for Expression {
|
||||
Self::Let(let_) => let_.collect_errors(errors),
|
||||
Self::Setq(setq) => setq.collect_errors(errors),
|
||||
Self::Defmacro(defmacro) => defmacro.collect_errors(errors),
|
||||
Self::While(cloop) => cloop.collect_errors(errors),
|
||||
Self::Nil
|
||||
| Self::IntegerLiteral(_)
|
||||
| Self::Identifier(_)
|
||||
|
||||
+47
-8
@@ -3,11 +3,12 @@ use std::{
|
||||
io::{self, BufReader},
|
||||
path::{Path, PathBuf},
|
||||
process::ExitCode,
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
use clap::Parser;
|
||||
use lysp::{
|
||||
compile::{CompileError, ParseError},
|
||||
compile::{CompileError, CompileOptions, ParseError},
|
||||
error::{EvalError, MachineErrorKind},
|
||||
read::{InteractiveReader, ModuleReader, read},
|
||||
util::Either,
|
||||
@@ -25,8 +26,32 @@ enum Error {
|
||||
Printed,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Trace {
|
||||
Compile,
|
||||
Execute,
|
||||
}
|
||||
|
||||
impl FromStr for Trace {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"compile" => Ok(Self::Compile),
|
||||
"execute" => Ok(Self::Execute),
|
||||
_ => Err(format!("Unknown trace flag: {s:?}")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
struct Args {
|
||||
#[clap(
|
||||
short = 'T',
|
||||
long = "trace",
|
||||
help = "Enable tracing of execution/compilation steps"
|
||||
)]
|
||||
trace: Vec<Trace>,
|
||||
module: Option<PathBuf>,
|
||||
}
|
||||
|
||||
@@ -88,8 +113,13 @@ fn handle_module_error(input: Either<EvalError, Vec<ParseError>>) -> Error {
|
||||
}
|
||||
}
|
||||
|
||||
fn eval(vm: &mut Machine, env: &mut Environment, value: Value) -> Option<Value> {
|
||||
let result = vm.eval_value(env, value.clone());
|
||||
fn eval(
|
||||
options: &CompileOptions,
|
||||
vm: &mut Machine,
|
||||
env: &mut Environment,
|
||||
value: Value,
|
||||
) -> Option<Value> {
|
||||
let result = vm.eval_value(options.clone(), env, value.clone());
|
||||
match result {
|
||||
Ok(r) => Some(r),
|
||||
Err(error) => {
|
||||
@@ -99,7 +129,11 @@ fn eval(vm: &mut Machine, env: &mut Environment, value: Value) -> Option<Value>
|
||||
}
|
||||
}
|
||||
|
||||
fn run_interactive(vm: &mut Machine, env: &mut Environment) -> Result<(), Error> {
|
||||
fn run_interactive(
|
||||
compile_options: &CompileOptions,
|
||||
vm: &mut Machine,
|
||||
env: &mut Environment,
|
||||
) -> Result<(), Error> {
|
||||
let mut reader = InteractiveReader::new("> ", ">> ");
|
||||
|
||||
loop {
|
||||
@@ -111,7 +145,7 @@ fn run_interactive(vm: &mut Machine, env: &mut Environment) -> Result<(), Error>
|
||||
continue;
|
||||
}
|
||||
};
|
||||
if let Some(value) = eval(vm, env, value) {
|
||||
if let Some(value) = eval(compile_options, vm, env, value) {
|
||||
println!("== {value}");
|
||||
} else {
|
||||
reader.reset();
|
||||
@@ -122,6 +156,7 @@ fn run_interactive(vm: &mut Machine, env: &mut Environment) -> Result<(), Error>
|
||||
}
|
||||
|
||||
fn run_module<P: AsRef<Path>>(
|
||||
compile_options: &CompileOptions,
|
||||
vm: &mut Machine,
|
||||
env: &mut Environment,
|
||||
path: P,
|
||||
@@ -129,7 +164,7 @@ fn run_module<P: AsRef<Path>>(
|
||||
let path = path.as_ref();
|
||||
let reader = BufReader::new(File::open(path)?);
|
||||
let module_reader = ModuleReader::new(reader);
|
||||
let module = match module_reader.compile(env) {
|
||||
let module = match module_reader.compile(compile_options, env) {
|
||||
Ok(module) => module,
|
||||
Err(error) => return Err(handle_module_error(error)),
|
||||
};
|
||||
@@ -143,11 +178,15 @@ fn run_module<P: AsRef<Path>>(
|
||||
fn main() -> ExitCode {
|
||||
let args = Args::parse();
|
||||
let mut vm = Machine::default();
|
||||
let compile_options = CompileOptions {
|
||||
trace_compile: args.trace.contains(&Trace::Compile),
|
||||
};
|
||||
vm.trace_instructions = args.trace.contains(&Trace::Execute);
|
||||
let mut env = Environment::default();
|
||||
prelude::load(&mut env);
|
||||
let result = match args.module.as_ref() {
|
||||
Some(module) => run_module(&mut vm, &mut env, module),
|
||||
None => run_interactive(&mut vm, &mut env),
|
||||
Some(module) => run_module(&compile_options, &mut vm, &mut env, module),
|
||||
None => run_interactive(&compile_options, &mut vm, &mut env),
|
||||
};
|
||||
match result {
|
||||
Ok(()) => ExitCode::SUCCESS,
|
||||
|
||||
+8
-4
@@ -5,7 +5,9 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
compile::{CompilationModule, Expression, FunctionBody, FunctionSignature, ParseError},
|
||||
compile::{
|
||||
CompilationModule, CompileOptions, Expression, FunctionBody, FunctionSignature, ParseError,
|
||||
},
|
||||
error::EvalError,
|
||||
parse::{self, parse_value},
|
||||
util::Either,
|
||||
@@ -106,6 +108,7 @@ impl<R: BufRead> ModuleReader<R> {
|
||||
|
||||
pub fn read_expression(
|
||||
&mut self,
|
||||
options: &CompileOptions,
|
||||
env: &mut Environment,
|
||||
) -> Result<Option<Rc<Expression>>, Either<EvalError, Vec<ParseError>>> {
|
||||
loop {
|
||||
@@ -117,7 +120,7 @@ impl<R: BufRead> ModuleReader<R> {
|
||||
let expression = Expression::parse(&value).map_err(Either::Right)?;
|
||||
if let Expression::Defmacro(_) = expression.as_ref() {
|
||||
self.macro_machine
|
||||
.eval_value(env, value)
|
||||
.eval_value(options.clone(), env, value)
|
||||
.map_err(Either::Left)?;
|
||||
continue;
|
||||
}
|
||||
@@ -127,9 +130,10 @@ impl<R: BufRead> ModuleReader<R> {
|
||||
|
||||
pub fn compile(
|
||||
mut self,
|
||||
options: &CompileOptions,
|
||||
env: &mut Environment,
|
||||
) -> Result<ModuleRef, Either<EvalError, Vec<ParseError>>> {
|
||||
let mut module = CompilationModule::default();
|
||||
let mut module = CompilationModule::new(options.clone());
|
||||
let mut body = FunctionBody {
|
||||
head: vec![],
|
||||
tail: Rc::new(Expression::Nil),
|
||||
@@ -138,7 +142,7 @@ impl<R: BufRead> ModuleReader<R> {
|
||||
let mut syntax_errors = vec![];
|
||||
|
||||
loop {
|
||||
let expression = match self.read_expression(env) {
|
||||
let expression = match self.read_expression(options, env) {
|
||||
Ok(Some(expression)) => expression,
|
||||
Ok(None) => break,
|
||||
Err(Either::Left(error)) => return Err(Either::Left(error)),
|
||||
|
||||
@@ -91,7 +91,7 @@ pub enum Instruction {
|
||||
}
|
||||
|
||||
pub type ConstantId = U<12>;
|
||||
pub type FunctionOffset = U<12>;
|
||||
pub type FunctionOffset = U<10>;
|
||||
pub type LocalId = U<8>;
|
||||
pub type ArgumentId = U<6>;
|
||||
pub type ArgumentCount = U<6>;
|
||||
@@ -222,7 +222,7 @@ impl TryFrom<u32> for Instruction {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::vm::instruction::U;
|
||||
use crate::vm::instruction::{FunctionOffset, U};
|
||||
|
||||
#[test]
|
||||
fn test_u_convert() {
|
||||
@@ -238,4 +238,10 @@ mod tests {
|
||||
let t = T::from_signed(-0x1000001);
|
||||
assert!(t.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_branch_target_extend() {
|
||||
let target = FunctionOffset::truncate(1022);
|
||||
assert_eq!(target.sign_extend_i64(), -2);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -1,6 +1,7 @@
|
||||
use std::{collections::HashMap, fmt};
|
||||
|
||||
use crate::{
|
||||
compile::CompileOptions,
|
||||
error::{EvalError, MachineError, MachineErrorKind},
|
||||
vm::{
|
||||
env::Environment,
|
||||
@@ -516,11 +517,12 @@ impl Machine {
|
||||
|
||||
pub fn eval_value(
|
||||
&mut self,
|
||||
compile_options: CompileOptions,
|
||||
environment: &mut Environment,
|
||||
value: Value,
|
||||
) -> Result<Value, EvalError> {
|
||||
let value = value.macro_expand(self, environment, false)?;
|
||||
let module = Module::compile_value(&value)?;
|
||||
let module = Module::compile_value(compile_options, &value)?;
|
||||
let module = ModuleRef::from(module);
|
||||
self.eval_module(environment, module)
|
||||
}
|
||||
|
||||
+14
-8
@@ -7,7 +7,10 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
compile::{CompilationModule, CompileError, Expression, FunctionBody, FunctionSignature},
|
||||
compile::{
|
||||
CompilationModule, CompileError, CompileOptions, Expression, FunctionBody,
|
||||
FunctionSignature,
|
||||
},
|
||||
vm::{
|
||||
instruction::{ConstantId, Instruction},
|
||||
pool::Pool,
|
||||
@@ -122,9 +125,9 @@ impl Module {
|
||||
self.entry
|
||||
}
|
||||
|
||||
pub fn compile_value(value: &Value) -> Result<Self, CompileError> {
|
||||
pub fn compile_value(options: CompileOptions, value: &Value) -> Result<Self, CompileError> {
|
||||
let expression = Expression::parse(value).map_err(CompileError::Parse)?;
|
||||
let mut module = CompilationModule::default();
|
||||
let mut module = CompilationModule::new(options);
|
||||
module.compile_function(
|
||||
FunctionSignature::EMPTY,
|
||||
&FunctionBody {
|
||||
@@ -215,10 +218,13 @@ impl fmt::Display for ModuleConstant {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::vm::{
|
||||
instruction::{Instruction, MathInstruction, U},
|
||||
module::Module,
|
||||
value::Value,
|
||||
use crate::{
|
||||
compile::CompileOptions,
|
||||
vm::{
|
||||
instruction::{Instruction, MathInstruction, U},
|
||||
module::Module,
|
||||
value::Value,
|
||||
},
|
||||
};
|
||||
|
||||
#[test]
|
||||
@@ -228,7 +234,7 @@ mod tests {
|
||||
Value::Integer(1),
|
||||
Value::Integer(2),
|
||||
]);
|
||||
let m = Module::compile_value(&v).unwrap();
|
||||
let m = Module::compile_value(CompileOptions::default(), &v).unwrap();
|
||||
assert!(m.constants.is_empty());
|
||||
let is = [
|
||||
Instruction::PushInteger(U::truncate(2)),
|
||||
|
||||
@@ -102,7 +102,7 @@ pub fn load(env: &mut Environment) {
|
||||
[_, _] => todo!(),
|
||||
_ => todo!(),
|
||||
};
|
||||
let value = match vm.eval_value(env, value.clone()) {
|
||||
let value = match vm.eval_value(Default::default(), env, value.clone()) {
|
||||
Ok(result) => result,
|
||||
_ => todo!(),
|
||||
};
|
||||
|
||||
@@ -30,7 +30,7 @@ fn eval_str_in(code: &str, env: &mut Environment) -> Result<Value, EvalError> {
|
||||
Err(error) => panic!("{error}"),
|
||||
};
|
||||
|
||||
last_value = Some(machine.eval_value(env, value));
|
||||
last_value = Some(machine.eval_value(Default::default(), env, value));
|
||||
}
|
||||
|
||||
last_value.expect("no expressions evaluated")
|
||||
|
||||
Reference in New Issue
Block a user