Skip to content

Commit

Permalink
Abstract away runtime.evaluate_anonymous_expression(), which handles …
Browse files Browse the repository at this point in the history
…resolving, compiling and running, analogous to runtime.load_ast_as_module().
  • Loading branch information
Ivorforce committed Jul 18, 2024
1 parent f32f7f4 commit ce2ac8e
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 29 deletions.
33 changes: 33 additions & 0 deletions src/interpreter/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ use crate::{ast, parser, program, resolver};
use crate::error::{RResult, RuntimeError};
use crate::interpreter::builtins;
use crate::interpreter::compile::compile_server::CompileServer;
use crate::interpreter::data::Value;
use crate::interpreter::vm::VM;
use crate::program::functions::{FunctionHead, FunctionInterface, FunctionLogic, FunctionRepresentation};
use crate::program::module::{Module, module_name, ModuleName};
use crate::program::traits::Trait;
use crate::repository::Repository;
use crate::resolver::{imports, referencible, scopes};
use crate::resolver::function::resolve_anonymous_expression;
use crate::source::Source;

pub struct Runtime {
Expand Down Expand Up @@ -113,4 +117,33 @@ impl Runtime {
resolver::resolve_file(syntax, &scope, self, &mut module)?;
Ok(module)
}

pub fn evaluate_anonymous_expression(&mut self, expression: &ast::Expression, interface: Rc<FunctionInterface>) -> RResult<Value> {
// It doesn't make sense to evaluate something that isn't supposed to return anything.
assert!(!interface.return_type.unit.is_void());

let scope = self.make_scope()?;

let implementation = resolve_anonymous_expression(
&interface, &expression, &scope, self
)?;

// TODO We shouldn't need a function head for this, I think.
let dummy_head = FunctionHead::new_static(
vec![],
FunctionRepresentation::dummy(),
interface,
);
self.source.fn_heads.insert(dummy_head.function_id, Rc::clone(&dummy_head));
self.source.fn_logic.insert(Rc::clone(&dummy_head), FunctionLogic::Implementation(implementation));

let compiled = self.compile_server.compile_deep(&self.source, &dummy_head)?;

let mut out: Vec<u8> = vec![];
let mut vm = VM::new(&mut out);
let result = vm.run(compiled, self, vec![])?;

// We know by now that the expression is supposed to evaluate to something.
return Ok(result.ok_or(RuntimeError::error("").to_array())?)
}
}
38 changes: 9 additions & 29 deletions src/interpreter/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@ mod tests {
use crate::interpreter::runtime::Runtime;
use crate::interpreter::vm::VM;
use crate::parser::parse_expression;
use crate::program::functions::{FunctionHead, FunctionInterface, FunctionLogic, FunctionRepresentation};
use crate::program::functions::FunctionInterface;
use crate::program::module::module_name;
use crate::program::types::TypeProto;
use crate::resolver::function::resolve_anonymous_expression;
use crate::transpiler::LanguageContext;

/// This tests the transpiler, interpreter and function calls.
Expand Down Expand Up @@ -180,36 +179,17 @@ mod tests {
let mut runtime = Runtime::new()?;
runtime.repository.add("common", PathBuf::from("monoteny"));

let (parsed_source, _) = parse_expression("String")?;

let function_interface = FunctionInterface::new_provider(
&TypeProto::one_arg(&runtime.Metatype, TypeProto::unit_struct(&runtime.traits.as_ref().unwrap().String)),
vec![]
);

let mut scope = runtime.make_scope()?;

let implementation = resolve_anonymous_expression(
&function_interface, &parsed_source, &scope, &mut runtime
let (expression, _) = parse_expression("String")?;
let result = runtime.evaluate_anonymous_expression(
&expression,
FunctionInterface::new_provider(
&TypeProto::one_arg(&runtime.Metatype, TypeProto::unit_struct(&runtime.traits.as_ref().unwrap().String)),
vec![]
),
)?;

// TODO We shouldn't need a function head for this.
let dummy_head = FunctionHead::new_static(
vec![],
FunctionRepresentation::dummy(),
function_interface,
);
runtime.source.fn_heads.insert(dummy_head.function_id, Rc::clone(&dummy_head));
runtime.source.fn_logic.insert(Rc::clone(&dummy_head), FunctionLogic::Implementation(implementation));

let compiled = runtime.compile_server.compile_deep(&runtime.source, &dummy_head)?;

let mut out: Vec<u8> = vec![];
let mut vm = VM::new(&mut out);
let result = vm.run(compiled, &mut runtime, vec![])?;

unsafe {
let uuid = *(result.unwrap().ptr as *mut Uuid);
let uuid = *(result.ptr as *mut Uuid);
assert_eq!(uuid, runtime.traits.unwrap().String.id);
}

Expand Down

0 comments on commit ce2ac8e

Please sign in to comment.