cl-interpret: Change struct layout, add rudimentary operator overloading
This commit is contained in:
parent
f41e5fc49a
commit
df9973b119
@ -41,6 +41,12 @@ impl std::fmt::Debug for Builtin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Builtin {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.write_str(self.desc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl super::Callable for Builtin {
|
impl super::Callable for Builtin {
|
||||||
fn call(&self, interpreter: &mut Environment, args: &[ConValue]) -> IResult<ConValue> {
|
fn call(&self, interpreter: &mut Environment, args: &[ConValue]) -> IResult<ConValue> {
|
||||||
(self.func)(interpreter, args)
|
(self.func)(interpreter, args)
|
||||||
@ -342,30 +348,22 @@ pub const Math: &[Builtin] = &builtins![
|
|||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn RangeExc(start, end) @env {
|
fn RangeExc(start, end) @env {
|
||||||
Ok(ConValue::TupleStruct(Box::new((
|
Ok(ConValue::TupleStruct("RangeExc".into(), Box::new(Box::new([start.clone(), end.clone()]))))
|
||||||
"RangeExc", Box::new([start.clone(), end.clone()])
|
|
||||||
))))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn RangeInc(start, end) @env {
|
fn RangeInc(start, end) @env {
|
||||||
Ok(ConValue::TupleStruct(Box::new((
|
Ok(ConValue::TupleStruct("RangeInc".into(), Box::new(Box::new([start.clone(), end.clone()]))))
|
||||||
"RangeInc", Box::new([start.clone(), end.clone()])
|
|
||||||
))))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn RangeTo(end) @env {
|
fn RangeTo(end) @env {
|
||||||
Ok(ConValue::TupleStruct(Box::new((
|
Ok(ConValue::TupleStruct("RangeTo".into(), Box::new(Box::new([end.clone()]))))
|
||||||
"RangeTo", Box::new([end.clone()])
|
|
||||||
))))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn RangeToInc(end) @env {
|
fn RangeToInc(end) @env {
|
||||||
Ok(ConValue::TupleStruct(Box::new((
|
Ok(ConValue::TupleStruct("RangeToInc".into(), Box::new(Box::new([end.clone()]))))
|
||||||
"RangeToInc", Box::new([end.clone()])
|
|
||||||
))))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Negates the ConValue
|
/// Negates the ConValue
|
||||||
|
@ -63,16 +63,15 @@ pub enum ConValue {
|
|||||||
Array(Box<[ConValue]>),
|
Array(Box<[ConValue]>),
|
||||||
/// A tuple
|
/// A tuple
|
||||||
Tuple(Box<[ConValue]>),
|
Tuple(Box<[ConValue]>),
|
||||||
|
// TODO: Instead of storing the identifier, store the index of the struct module
|
||||||
/// A value of a product type
|
/// A value of a product type
|
||||||
Struct(Box<(&'static str, HashMap<Sym, ConValue>)>),
|
Struct(Sym, Box<HashMap<Sym, ConValue>>),
|
||||||
/// A value of a product type with anonymous members
|
/// A value of a product type with anonymous members
|
||||||
TupleStruct(Box<(&'static str, Box<[ConValue]>)>),
|
TupleStruct(Sym, Box<Box<[ConValue]>>),
|
||||||
/// An entire namespace
|
/// An entire namespace
|
||||||
Module(Box<HashMap<Sym, ConValue>>),
|
Module(Box<HashMap<Sym, ConValue>>),
|
||||||
/// A namespace, sans storage
|
|
||||||
Module2(HashMap<Sym, usize>),
|
|
||||||
/// A quoted expression
|
/// A quoted expression
|
||||||
Quote(Box<Expr>),
|
Quote(Rc<Expr>),
|
||||||
/// A callable thing
|
/// A callable thing
|
||||||
Function(Rc<Function>),
|
Function(Rc<Function>),
|
||||||
/// A tuple constructor
|
/// A tuple constructor
|
||||||
@ -92,8 +91,8 @@ impl ConValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn typename(&self) -> IResult<&'static str> {
|
pub fn typename(&self) -> &'static str {
|
||||||
Ok(match self {
|
match self {
|
||||||
ConValue::Empty => "Empty",
|
ConValue::Empty => "Empty",
|
||||||
ConValue::Int(_) => "i64",
|
ConValue::Int(_) => "i64",
|
||||||
ConValue::Float(_) => "f64",
|
ConValue::Float(_) => "f64",
|
||||||
@ -105,25 +104,24 @@ impl ConValue {
|
|||||||
ConValue::Slice(_, _) => "Slice",
|
ConValue::Slice(_, _) => "Slice",
|
||||||
ConValue::Array(_) => "Array",
|
ConValue::Array(_) => "Array",
|
||||||
ConValue::Tuple(_) => "Tuple",
|
ConValue::Tuple(_) => "Tuple",
|
||||||
ConValue::Struct(_) => "Struct",
|
ConValue::Struct(_, _) => "Struct",
|
||||||
ConValue::TupleStruct(_) => "TupleStruct",
|
ConValue::TupleStruct(_, _) => "TupleStruct",
|
||||||
ConValue::Module(_) => "",
|
ConValue::Module(_) => "",
|
||||||
ConValue::Module2(_) => "",
|
|
||||||
ConValue::Quote(_) => "Quote",
|
ConValue::Quote(_) => "Quote",
|
||||||
ConValue::Function(_) => "Fn",
|
ConValue::Function(_) => "Fn",
|
||||||
ConValue::TupleConstructor(_) => "Fn",
|
ConValue::TupleConstructor(_) => "Fn",
|
||||||
ConValue::Closure(_) => "Fn",
|
ConValue::Closure(_) => "Fn",
|
||||||
ConValue::Builtin(_) => "Fn",
|
ConValue::Builtin(_) => "Fn",
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn TupleStruct(id: Sym, values: Box<[ConValue]>) -> Self {
|
pub fn TupleStruct(id: Sym, values: Box<[ConValue]>) -> Self {
|
||||||
Self::TupleStruct(Box::new((id.to_ref(), values)))
|
Self::TupleStruct(id, Box::new(values))
|
||||||
}
|
}
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn Struct(id: Sym, values: HashMap<Sym, ConValue>) -> Self {
|
pub fn Struct(id: Sym, values: HashMap<Sym, ConValue>) -> Self {
|
||||||
Self::Struct(Box::new((id.to_ref(), values)))
|
Self::Struct(id, Box::new(values))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn index(&self, index: &Self, _env: &Environment) -> IResult<ConValue> {
|
pub fn index(&self, index: &Self, _env: &Environment) -> IResult<ConValue> {
|
||||||
@ -393,8 +391,7 @@ impl std::fmt::Display for ConValue {
|
|||||||
}
|
}
|
||||||
')'.fmt(f)
|
')'.fmt(f)
|
||||||
}
|
}
|
||||||
ConValue::TupleStruct(parts) => {
|
ConValue::TupleStruct(id, tuple) => {
|
||||||
let (id, tuple) = parts.as_ref();
|
|
||||||
write!(f, "{id}")?;
|
write!(f, "{id}")?;
|
||||||
'('.fmt(f)?;
|
'('.fmt(f)?;
|
||||||
for (idx, element) in tuple.iter().enumerate() {
|
for (idx, element) in tuple.iter().enumerate() {
|
||||||
@ -405,8 +402,7 @@ impl std::fmt::Display for ConValue {
|
|||||||
}
|
}
|
||||||
')'.fmt(f)
|
')'.fmt(f)
|
||||||
}
|
}
|
||||||
ConValue::Struct(parts) => {
|
ConValue::Struct(id, map) => {
|
||||||
let (id, map) = parts.as_ref();
|
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
write!(f, "{id} ")?;
|
write!(f, "{id} ")?;
|
||||||
let mut f = f.delimit_with("{", "\n}");
|
let mut f = f.delimit_with("{", "\n}");
|
||||||
@ -423,14 +419,6 @@ impl std::fmt::Display for ConValue {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
ConValue::Module2(module) => {
|
|
||||||
use std::fmt::Write;
|
|
||||||
let mut f = f.delimit_with("{", "\n}");
|
|
||||||
for (k, v) in module.iter() {
|
|
||||||
write!(f, "\n{k}: <{v}>,")?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
ConValue::Quote(q) => {
|
ConValue::Quote(q) => {
|
||||||
write!(f, "`{q}`")
|
write!(f, "`{q}`")
|
||||||
}
|
}
|
||||||
@ -444,7 +432,7 @@ impl std::fmt::Display for ConValue {
|
|||||||
write!(f, "{}", func.as_ref())
|
write!(f, "{}", func.as_ref())
|
||||||
}
|
}
|
||||||
ConValue::Builtin(func) => {
|
ConValue::Builtin(func) => {
|
||||||
write!(f, "{}", func.description())
|
write!(f, "{}", func)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
//! meaningless to get a pointer to one, and would be undefined behavior to dereference a pointer to
|
//! meaningless to get a pointer to one, and would be undefined behavior to dereference a pointer to
|
||||||
//! one in any situation.
|
//! one in any situation.
|
||||||
|
|
||||||
|
use crate::constructor::Constructor;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use cl_ast::{ast_visitor::Visit, *};
|
use cl_ast::{ast_visitor::Visit, *};
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
@ -144,12 +146,13 @@ impl Interpret for Struct {
|
|||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
StructKind::Empty => {
|
StructKind::Empty => {
|
||||||
frame.insert_tup_constructor("call".into(), 0);
|
let cs = Constructor { arity: 0, name: *name };
|
||||||
|
frame.insert("call".into(), ConValue::TupleConstructor(cs));
|
||||||
frame.insert("__nmemb".into(), ConValue::Int(0));
|
frame.insert("__nmemb".into(), ConValue::Int(0));
|
||||||
}
|
}
|
||||||
StructKind::Tuple(args) => {
|
StructKind::Tuple(args) => {
|
||||||
// Constructs the AST from scratch. TODO: This, better.
|
let cs = Constructor { arity: args.len() as _, name: *name };
|
||||||
frame.insert_tup_constructor("call".into(), args.len());
|
frame.insert("call".into(), ConValue::TupleConstructor(cs));
|
||||||
frame.insert("__nmemb".into(), ConValue::Int(args.len() as _));
|
frame.insert("__nmemb".into(), ConValue::Int(args.len() as _));
|
||||||
}
|
}
|
||||||
StructKind::Struct(members) => {
|
StructKind::Struct(members) => {
|
||||||
@ -185,7 +188,8 @@ impl Interpret for Enum {
|
|||||||
scope.insert(*name, idx)
|
scope.insert(*name, idx)
|
||||||
}
|
}
|
||||||
(StructKind::Tuple(args), None) => {
|
(StructKind::Tuple(args), None) => {
|
||||||
scope.insert_tup_constructor(*name, args.len());
|
let cs = Constructor { arity: args.len() as _, name: *name };
|
||||||
|
scope.insert("call".into(), ConValue::TupleConstructor(cs));
|
||||||
}
|
}
|
||||||
(StructKind::Struct(_), None) => {}
|
(StructKind::Struct(_), None) => {}
|
||||||
_ => eprintln!("Well-formedness error in {self}"),
|
_ => eprintln!("Well-formedness error in {self}"),
|
||||||
@ -360,7 +364,7 @@ impl Interpret for Closure {
|
|||||||
impl Interpret for Quote {
|
impl Interpret for Quote {
|
||||||
fn interpret(&self, _env: &mut Environment) -> IResult<ConValue> {
|
fn interpret(&self, _env: &mut Environment) -> IResult<ConValue> {
|
||||||
// TODO: squoosh down into a ConValue?
|
// TODO: squoosh down into a ConValue?
|
||||||
Ok(ConValue::Quote(self.quote.clone()))
|
Ok(ConValue::Quote(self.quote.as_ref().clone().into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,12 +510,12 @@ pub(crate) mod assignment {
|
|||||||
kind: &MemberKind,
|
kind: &MemberKind,
|
||||||
) -> IResult<&'v mut ConValue> {
|
) -> IResult<&'v mut ConValue> {
|
||||||
match (value, kind) {
|
match (value, kind) {
|
||||||
(ConValue::Struct(s), MemberKind::Struct(id)) => {
|
(ConValue::Struct(_name, s), MemberKind::Struct(id)) => {
|
||||||
s.1.get_mut(id).ok_or(Error::NotDefined(*id))
|
s.get_mut(id).ok_or(Error::NotDefined(*id))
|
||||||
}
|
}
|
||||||
(ConValue::TupleStruct(s), MemberKind::Tuple(Literal::Int(id))) => {
|
(ConValue::TupleStruct(_name, s), MemberKind::Tuple(Literal::Int(id))) => {
|
||||||
let len = s.1.len();
|
let len = s.len();
|
||||||
s.1.get_mut(*id as usize)
|
s.get_mut(*id as usize)
|
||||||
.ok_or(Error::OobIndex(*id as _, len))
|
.ok_or(Error::OobIndex(*id as _, len))
|
||||||
}
|
}
|
||||||
(ConValue::Tuple(t), MemberKind::Tuple(Literal::Int(id))) => {
|
(ConValue::Tuple(t), MemberKind::Tuple(Literal::Int(id))) => {
|
||||||
@ -613,6 +617,46 @@ impl Interpret for Binary {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let tail = tail.interpret(env)?;
|
let tail = tail.interpret(env)?;
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
let operator = match kind {
|
||||||
|
BinaryKind::Lt => "lt",
|
||||||
|
BinaryKind::LtEq => "lteq",
|
||||||
|
BinaryKind::Equal => "eq",
|
||||||
|
BinaryKind::NotEq => "neq",
|
||||||
|
BinaryKind::GtEq => "gteq",
|
||||||
|
BinaryKind::Gt => "gt",
|
||||||
|
BinaryKind::RangeExc => "range_exc",
|
||||||
|
BinaryKind::RangeInc => "range_inc",
|
||||||
|
BinaryKind::LogAnd => "log_and",
|
||||||
|
BinaryKind::LogOr => "log_or",
|
||||||
|
BinaryKind::LogXor => "log_xor",
|
||||||
|
BinaryKind::BitAnd => "bit_and",
|
||||||
|
BinaryKind::BitOr => "bit_or",
|
||||||
|
BinaryKind::BitXor => "bit_xor",
|
||||||
|
BinaryKind::Shl => "shl",
|
||||||
|
BinaryKind::Shr => "shr",
|
||||||
|
BinaryKind::Add => "add",
|
||||||
|
BinaryKind::Sub => "sub",
|
||||||
|
BinaryKind::Mul => "mul",
|
||||||
|
BinaryKind::Div => "div",
|
||||||
|
BinaryKind::Rem => "rem",
|
||||||
|
BinaryKind::Call => "call",
|
||||||
|
};
|
||||||
|
|
||||||
|
if let ConValue::Struct(name, _) | ConValue::TupleStruct(name, _) = head
|
||||||
|
&& let Ok(ConValue::Module(m)) = env.get_mut(name)
|
||||||
|
&& let Some(f) = m.get(&operator.into())
|
||||||
|
{
|
||||||
|
return f.clone().call(env, &[head, tail]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(ConValue::Module(m)) = env.get_mut(head.typename().into())
|
||||||
|
&& let Some(f) = m.get(&operator.into())
|
||||||
|
{
|
||||||
|
return f.clone().call(env, &[head, tail]);
|
||||||
|
}
|
||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
BinaryKind::Lt => head.lt(&tail),
|
BinaryKind::Lt => head.lt(&tail),
|
||||||
BinaryKind::LtEq => head.lt_eq(&tail),
|
BinaryKind::LtEq => head.lt_eq(&tail),
|
||||||
@ -645,61 +689,63 @@ impl Interpret for Binary {
|
|||||||
impl Interpret for Unary {
|
impl Interpret for Unary {
|
||||||
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
|
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
|
||||||
let Unary { kind, tail } = self;
|
let Unary { kind, tail } = self;
|
||||||
match kind {
|
if *kind == UnaryKind::Loop {
|
||||||
UnaryKind::Loop => loop {
|
loop {
|
||||||
match tail.interpret(env) {
|
match tail.interpret(env) {
|
||||||
Err(Error { kind: ErrorKind::Break(value), .. }) => break Ok(value),
|
Err(Error { kind: ErrorKind::Break(value), .. }) => return Ok(value),
|
||||||
Err(Error { kind: ErrorKind::Continue, .. }) => continue,
|
Err(Error { kind: ErrorKind::Continue, .. }) => continue,
|
||||||
e => e?,
|
e => e?,
|
||||||
};
|
};
|
||||||
},
|
|
||||||
UnaryKind::Deref => {
|
|
||||||
let operand = tail.interpret(env)?;
|
|
||||||
env.call("deref".into(), &[operand])
|
|
||||||
}
|
}
|
||||||
UnaryKind::Neg => {
|
|
||||||
let operand = tail.interpret(env)?;
|
|
||||||
env.call("neg".into(), &[operand])
|
|
||||||
}
|
|
||||||
UnaryKind::Not => {
|
|
||||||
let operand = tail.interpret(env)?;
|
|
||||||
env.call("not".into(), &[operand])
|
|
||||||
}
|
|
||||||
UnaryKind::RangeExc => {
|
|
||||||
let operand = tail.interpret(env)?;
|
|
||||||
env.call("RangeTo".into(), &[operand])
|
|
||||||
}
|
|
||||||
UnaryKind::RangeInc => {
|
|
||||||
let operand = tail.interpret(env)?;
|
|
||||||
env.call("RangeToInc".into(), &[operand])
|
|
||||||
}
|
|
||||||
UnaryKind::At => {
|
|
||||||
let operand = tail.interpret(env)?;
|
|
||||||
println!("{operand}");
|
|
||||||
Ok(operand)
|
|
||||||
}
|
|
||||||
UnaryKind::Tilde => unimplemented!("Tilde operator"),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let operator = match kind {
|
||||||
|
UnaryKind::Loop => unreachable!(),
|
||||||
|
UnaryKind::Deref => "deref",
|
||||||
|
UnaryKind::Neg => "neg",
|
||||||
|
UnaryKind::Not => "not",
|
||||||
|
UnaryKind::RangeExc => "RangeTo",
|
||||||
|
UnaryKind::RangeInc => "RangeToInc",
|
||||||
|
UnaryKind::At => "at",
|
||||||
|
UnaryKind::Tilde => "tilde",
|
||||||
|
};
|
||||||
|
|
||||||
|
let operand = tail.interpret(env)?;
|
||||||
|
|
||||||
|
if let ConValue::Struct(name, _) | ConValue::TupleStruct(name, _) = operand
|
||||||
|
&& let Ok(ConValue::Module(m)) = env.get_mut(name)
|
||||||
|
&& let Some(f) = m.get(&operator.into())
|
||||||
|
{
|
||||||
|
return f.clone().call(env, &[operand]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(ConValue::Module(m)) = env.get_mut(operand.typename().into())
|
||||||
|
&& let Some(f) = m.get(&operator.into())
|
||||||
|
{
|
||||||
|
return f.clone().call(env, &[operand]);
|
||||||
|
}
|
||||||
|
|
||||||
|
env.call(operator.into(), &[operand])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cast(env: &Environment, value: ConValue, ty: Sym) -> IResult<ConValue> {
|
fn cast(env: &Environment, value: ConValue, ty: Sym) -> IResult<ConValue> {
|
||||||
let value = match value {
|
let value = match (value, ty.to_ref()) {
|
||||||
ConValue::Empty => 0,
|
(value, "str") => return Ok(ConValue::Str(format!("{value}").into())),
|
||||||
ConValue::Int(i) => i as _,
|
(value, "String") => return Ok(ConValue::String(format!("{value}"))),
|
||||||
ConValue::Bool(b) => b as _,
|
(ConValue::Empty, _) => 0,
|
||||||
ConValue::Char(c) => c as _,
|
(ConValue::Int(i), _) => i as _,
|
||||||
ConValue::Ref(v) => {
|
(ConValue::Bool(b), _) => b as _,
|
||||||
|
(ConValue::Char(c), _) => c as _,
|
||||||
|
(ConValue::Ref(v), _) => {
|
||||||
return cast(
|
return cast(
|
||||||
env,
|
env,
|
||||||
env.get_id(v).cloned().ok_or(Error::StackUnderflow())?,
|
env.get_id(v).cloned().ok_or(Error::StackUnderflow())?,
|
||||||
ty,
|
ty,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// TODO: This, better
|
(ConValue::Float(f), "f32" | "f64") => return Ok(ConValue::Float(f)),
|
||||||
ConValue::Float(_) if ty.starts_with('f') => return Ok(value),
|
(ConValue::Float(f), _) => f as _,
|
||||||
ConValue::Float(f) => f as _,
|
|
||||||
_ if (*ty).eq("str") => return Ok(ConValue::Str(format!("{value}").into())),
|
|
||||||
_ => Err(Error::TypeError())?,
|
_ => Err(Error::TypeError())?,
|
||||||
};
|
};
|
||||||
Ok(match &*ty {
|
Ok(match &*ty {
|
||||||
@ -714,7 +760,7 @@ fn cast(env: &Environment, value: ConValue, ty: Sym) -> IResult<ConValue> {
|
|||||||
"f32" => ConValue::Float(value as f32 as _),
|
"f32" => ConValue::Float(value as f32 as _),
|
||||||
"f64" => ConValue::Float(value as f64 as _),
|
"f64" => ConValue::Float(value as f64 as _),
|
||||||
"char" => ConValue::Char(char::from_u32(value as _).unwrap_or('\u{fffd}')),
|
"char" => ConValue::Char(char::from_u32(value as _).unwrap_or('\u{fffd}')),
|
||||||
"bool" => ConValue::Bool(value < 0),
|
"bool" => ConValue::Bool(value != 0),
|
||||||
_ => Err(Error::NotDefined(ty))?,
|
_ => Err(Error::NotDefined(ty))?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -761,10 +807,10 @@ impl Interpret for Member {
|
|||||||
|
|
||||||
// Perform alternate member access
|
// Perform alternate member access
|
||||||
match (&value, &kind) {
|
match (&value, &kind) {
|
||||||
(ConValue::Struct(parts), MemberKind::Call(name, args))
|
(ConValue::Struct(_name, memb), MemberKind::Call(name, args))
|
||||||
if parts.1.contains_key(name) =>
|
if memb.contains_key(name) =>
|
||||||
{
|
{
|
||||||
let f = parts.1.get(name).cloned().expect("function exists");
|
let f = memb.get(name).cloned().expect("function exists");
|
||||||
values.push(addr.unwrap_or(value));
|
values.push(addr.unwrap_or(value));
|
||||||
for arg in &args.exprs {
|
for arg in &args.exprs {
|
||||||
values.push(arg.interpret(env)?);
|
values.push(arg.interpret(env)?);
|
||||||
@ -801,10 +847,10 @@ impl Interpret for Structor {
|
|||||||
// use that definition to place the struct parts
|
// use that definition to place the struct parts
|
||||||
|
|
||||||
let name = match parts.last() {
|
let name = match parts.last() {
|
||||||
Some(PathPart::Ident(name)) => name.to_ref(),
|
Some(PathPart::Ident(name)) => *name,
|
||||||
Some(PathPart::SelfTy) => "Self",
|
Some(PathPart::SelfTy) => "Self".into(),
|
||||||
Some(PathPart::SuperKw) => "super",
|
Some(PathPart::SuperKw) => "super".into(),
|
||||||
None => "",
|
None => "".into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut map = HashMap::new();
|
let mut map = HashMap::new();
|
||||||
@ -815,7 +861,7 @@ impl Interpret for Structor {
|
|||||||
};
|
};
|
||||||
map.insert(*name, value);
|
map.insert(*name, value);
|
||||||
}
|
}
|
||||||
Ok(ConValue::Struct(Box::new((name, map))))
|
Ok(ConValue::Struct(name, Box::new(map)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -942,15 +988,15 @@ impl Interpret for For {
|
|||||||
let cond = cond.interpret(env)?;
|
let cond = cond.interpret(env)?;
|
||||||
// TODO: A better iterator model
|
// TODO: A better iterator model
|
||||||
let mut bounds: Box<dyn Iterator<Item = ConValue>> = match &cond {
|
let mut bounds: Box<dyn Iterator<Item = ConValue>> = match &cond {
|
||||||
ConValue::TupleStruct(inner) => match &**inner {
|
ConValue::TupleStruct(name, values) => match name.to_ref() {
|
||||||
("RangeExc", values) => match **values {
|
"RangeExc" => match values.as_ref().as_ref() {
|
||||||
[ConValue::Int(from), ConValue::Int(to)] => {
|
&[ConValue::Int(from), ConValue::Int(to)] => {
|
||||||
Box::new((from..to).map(ConValue::Int))
|
Box::new((from..to).map(ConValue::Int))
|
||||||
}
|
}
|
||||||
_ => Err(Error::NotIterable())?,
|
_ => Err(Error::NotIterable())?,
|
||||||
},
|
},
|
||||||
("RangeInc", values) => match **values {
|
"RangeInc" => match values.as_ref().as_ref() {
|
||||||
[ConValue::Int(from), ConValue::Int(to)] => {
|
&[ConValue::Int(from), ConValue::Int(to)] => {
|
||||||
Box::new((from..=to).map(ConValue::Int))
|
Box::new((from..=to).map(ConValue::Int))
|
||||||
}
|
}
|
||||||
_ => Err(Error::NotIterable())?,
|
_ => Err(Error::NotIterable())?,
|
||||||
|
@ -43,10 +43,7 @@ pub mod constructor {
|
|||||||
fn call(&self, _env: &mut Environment, args: &[ConValue]) -> IResult<ConValue> {
|
fn call(&self, _env: &mut Environment, args: &[ConValue]) -> IResult<ConValue> {
|
||||||
let &Self { name, arity } = self;
|
let &Self { name, arity } = self;
|
||||||
if arity as usize == args.len() {
|
if arity as usize == args.len() {
|
||||||
Ok(ConValue::TupleStruct(Box::new((
|
Ok(ConValue::TupleStruct(name, Box::new(args.into())))
|
||||||
name.to_ref(),
|
|
||||||
args.into(),
|
|
||||||
))))
|
|
||||||
} else {
|
} else {
|
||||||
Err(Error::ArgNumber(arity as usize, args.len()))
|
Err(Error::ArgNumber(arity as usize, args.len()))
|
||||||
}
|
}
|
||||||
|
@ -294,13 +294,11 @@ pub fn append_sub(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(Pattern::TupleStruct(path, patterns), ConValue::TupleStruct(parts)) => {
|
(Pattern::TupleStruct(path, patterns), ConValue::TupleStruct(id, values)) => {
|
||||||
let (id, values) = *parts;
|
|
||||||
|
|
||||||
let tid = path
|
let tid = path
|
||||||
.as_sym()
|
.as_sym()
|
||||||
.ok_or_else(|| Error::PatFailed(pat.clone().into()))?;
|
.ok_or_else(|| Error::PatFailed(pat.clone().into()))?;
|
||||||
if id != tid.to_ref() {
|
if id != tid {
|
||||||
return Err(Error::PatFailed(pat.clone().into()));
|
return Err(Error::PatFailed(pat.clone().into()));
|
||||||
}
|
}
|
||||||
match rest_binding(env, sub, patterns, values.into_vec().into())? {
|
match rest_binding(env, sub, patterns, values.into_vec().into())? {
|
||||||
@ -311,12 +309,11 @@ pub fn append_sub(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(Pattern::Struct(path, patterns), ConValue::Struct(parts)) => {
|
(Pattern::Struct(path, patterns), ConValue::Struct(id, mut values)) => {
|
||||||
let (id, mut values) = *parts;
|
|
||||||
let tid = path
|
let tid = path
|
||||||
.as_sym()
|
.as_sym()
|
||||||
.ok_or_else(|| Error::PatFailed(pat.clone().into()))?;
|
.ok_or_else(|| Error::PatFailed(pat.clone().into()))?;
|
||||||
if id != tid.to_ref() {
|
if id != tid {
|
||||||
return Err(Error::PatFailed(pat.clone().into()));
|
return Err(Error::PatFailed(pat.clone().into()));
|
||||||
}
|
}
|
||||||
for (name, pat) in patterns {
|
for (name, pat) in patterns {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user