mirror of
https://github.com/MorizzG/rlox.git
synced 2025-12-06 04:12:42 +00:00
Lox Interpreter done (Chapter 13)
This commit is contained in:
parent
10540708d4
commit
719a014977
16 changed files with 707 additions and 196 deletions
|
|
@ -1,7 +1,10 @@
|
|||
use std::fmt::{Debug, Display};
|
||||
use std::rc::Rc;
|
||||
|
||||
use rlox2_frontend::parser::Stmt;
|
||||
|
||||
use crate::value::HeapedValue;
|
||||
|
||||
use super::environment::{Environment, Scope};
|
||||
use super::interpret::EvalResult;
|
||||
use super::{Runtime, Value};
|
||||
|
|
@ -15,19 +18,16 @@ pub struct LoxFunction {
|
|||
}
|
||||
|
||||
impl LoxFunction {
|
||||
pub fn new(name: impl Into<String>, closure: Scope, param_names: Vec<String>, body: Stmt) -> Self {
|
||||
pub fn new(name: impl Into<String>, closure: Scope, param_names: Vec<String>, body: Stmt) -> Rc<Self> {
|
||||
let name = name.into();
|
||||
let body = Box::new(body);
|
||||
LoxFunction {
|
||||
let fun = LoxFunction {
|
||||
name,
|
||||
closure,
|
||||
param_names,
|
||||
body,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn arity(&self) -> usize {
|
||||
self.param_names.len()
|
||||
};
|
||||
Rc::new(fun)
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
|
|
@ -38,13 +38,23 @@ impl LoxFunction {
|
|||
&self.closure
|
||||
}
|
||||
|
||||
pub fn param_names(&self) -> impl Iterator<Item = &String> {
|
||||
self.param_names.iter()
|
||||
pub fn param_names(&self) -> &[String] {
|
||||
&self.param_names
|
||||
}
|
||||
|
||||
pub fn body(&self) -> &Stmt {
|
||||
&self.body
|
||||
}
|
||||
|
||||
pub fn arity(&self) -> usize {
|
||||
self.param_names().len()
|
||||
}
|
||||
|
||||
pub fn inject_closed_var(&mut self, name: impl Into<String>, value: Value) {
|
||||
let name = name.into();
|
||||
let heaped_value = HeapedValue::new(value);
|
||||
self.closure.insert(name, heaped_value);
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for LoxFunction {
|
||||
|
|
@ -53,6 +63,16 @@ impl Display for LoxFunction {
|
|||
}
|
||||
}
|
||||
|
||||
// slightly hacky: two functions are equal if they are stored at the same location
|
||||
// since a LoxFunction is always (supposed to be) behind an Rc anyways, we might as well compare their pointers
|
||||
impl PartialEq for LoxFunction {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let self_ptr = self as *const LoxFunction;
|
||||
let other_ptr = other as *const LoxFunction;
|
||||
self_ptr == other_ptr
|
||||
}
|
||||
}
|
||||
|
||||
/*====================================================================================================================*/
|
||||
|
||||
pub type ExternFunClosure = fn(Vec<Value>, &mut Environment) -> EvalResult<Value>;
|
||||
|
|
@ -60,15 +80,27 @@ pub type ExternFunClosure = fn(Vec<Value>, &mut Environment) -> EvalResult<Value
|
|||
#[derive(Clone)]
|
||||
pub struct LoxExternFunction {
|
||||
name: String,
|
||||
|
||||
arity: usize,
|
||||
closure: ExternFunClosure,
|
||||
}
|
||||
|
||||
impl LoxExternFunction {
|
||||
pub fn new(name: impl Into<String>, closure: ExternFunClosure) -> Self {
|
||||
pub fn new(name: impl Into<String>, arity: usize, closure: ExternFunClosure) -> Self {
|
||||
let name = name.into();
|
||||
|
||||
LoxExternFunction { name, closure }
|
||||
LoxExternFunction { name, arity, closure }
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
pub fn arity(&self) -> usize {
|
||||
self.arity
|
||||
}
|
||||
|
||||
pub fn closure(&self) -> ExternFunClosure {
|
||||
self.closure
|
||||
}
|
||||
|
||||
pub fn register(self, env: &mut Runtime) {
|
||||
|
|
@ -76,10 +108,6 @@ impl LoxExternFunction {
|
|||
let fun = Value::extern_function(self);
|
||||
env.define_global(name, fun);
|
||||
}
|
||||
|
||||
pub fn call(&self, args: Vec<Value>, env: &mut Environment) -> EvalResult<Value> {
|
||||
(self.closure)(args, env)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for LoxExternFunction {
|
||||
|
|
@ -97,8 +125,12 @@ impl Debug for LoxExternFunction {
|
|||
}
|
||||
}
|
||||
|
||||
// slightly hacky: two extern functions are equal if they are stored at the same location
|
||||
// since a LoxExternFunction is always (supposed to be) behind an Rc anyways, we might as well compare their pointers
|
||||
impl PartialEq for LoxExternFunction {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.name == other.name
|
||||
let self_ptr = self as *const LoxExternFunction;
|
||||
let other_ptr = other as *const LoxExternFunction;
|
||||
self_ptr == other_ptr
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue