Compare commits
No commits in common. "de741448e0825bf32a4119270e0ae910a889239d" and "1c6545fb7451210caaf73e00c4e9f193b60b6074" have entirely different histories.
de741448e0
...
1c6545fb74
@ -196,7 +196,6 @@ pub enum ExpressionKind {
|
|||||||
WhileExpression { condition: Option<Box<Expression>>, body: Block },
|
WhileExpression { condition: Option<Box<Expression>>, body: Block },
|
||||||
ForExpression { enumerators: Vec<Enumerator>, body: Box<ForBody> },
|
ForExpression { enumerators: Vec<Enumerator>, body: Box<ForBody> },
|
||||||
Lambda { params: Vec<FormalParam>, type_anno: Option<TypeIdentifier>, body: Block },
|
Lambda { params: Vec<FormalParam>, type_anno: Option<TypeIdentifier>, body: Block },
|
||||||
Access { name: Rc<String>, expr: Box<Expression> },
|
|
||||||
ListLiteral(Vec<Expression>),
|
ListLiteral(Vec<Expression>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,9 +128,6 @@ pub fn walk_expression<V: ASTVisitor>(v: &mut V, expr: &Expression) {
|
|||||||
Lambda { params: _, type_anno: _, body } => {
|
Lambda { params: _, type_anno: _, body } => {
|
||||||
walk_block(v, body);
|
walk_block(v, body);
|
||||||
}
|
}
|
||||||
Access { name: _, expr } => {
|
|
||||||
walk_expression(v, expr);
|
|
||||||
}
|
|
||||||
ListLiteral(exprs) =>
|
ListLiteral(exprs) =>
|
||||||
for expr in exprs {
|
for expr in exprs {
|
||||||
walk_expression(v, expr);
|
walk_expression(v, expr);
|
||||||
|
@ -120,7 +120,6 @@ fn render_expression(expr: &Expression, indent: usize, buf: &mut String) {
|
|||||||
newline(buf);
|
newline(buf);
|
||||||
do_indent(indent, buf);
|
do_indent(indent, buf);
|
||||||
}
|
}
|
||||||
Access { .. } => buf.push_str("<access-expr>"),
|
|
||||||
ListLiteral(..) => buf.push_str("<list-literal>"),
|
ListLiteral(..) => buf.push_str("<list-literal>"),
|
||||||
}
|
}
|
||||||
buf.push(')');
|
buf.push(')');
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -203,36 +203,11 @@ fn operators() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn accessors() {
|
fn accessors() {
|
||||||
use ExpressionKind::*;
|
/*
|
||||||
|
assert_expr!("a.b");
|
||||||
assert_expr!("a.b", expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) }));
|
assert_expr!("a.b.c.d()");
|
||||||
assert_expr!(
|
assert_expr!("a.b().c.d()");
|
||||||
"a.b.c",
|
*/
|
||||||
expr(Access {
|
|
||||||
name: rc("c"),
|
|
||||||
expr: bx(expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) }))
|
|
||||||
})
|
|
||||||
);
|
|
||||||
assert_expr!(
|
|
||||||
"a.b.c(3)",
|
|
||||||
expr(Call {
|
|
||||||
f: bx(expr(Access {
|
|
||||||
name: rc("c"),
|
|
||||||
expr: bx(expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) }))
|
|
||||||
})),
|
|
||||||
arguments: vec![InvocationArgument::Positional(expr(NatLiteral(3)))],
|
|
||||||
})
|
|
||||||
);
|
|
||||||
assert_expr!(
|
|
||||||
"a.b().c",
|
|
||||||
expr(Access {
|
|
||||||
name: rc("c"),
|
|
||||||
expr: bx(expr(Call {
|
|
||||||
f: bx(expr(Access { name: rc("b"), expr: bx(expr(Value(qn!(a)))) })),
|
|
||||||
arguments: vec![]
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -4,7 +4,7 @@ use crate::{
|
|||||||
ast,
|
ast,
|
||||||
builtin::Builtin,
|
builtin::Builtin,
|
||||||
symbol_table::{DefId, SymbolSpec, SymbolTable},
|
symbol_table::{DefId, SymbolSpec, SymbolTable},
|
||||||
type_inference::{TypeContext, TypeId},
|
type_inference::TypeContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod test;
|
mod test;
|
||||||
@ -135,14 +135,23 @@ impl<'a, 'b> Reducer<'a, 'b> {
|
|||||||
}),
|
}),
|
||||||
NamedStruct { name, fields } => {
|
NamedStruct { name, fields } => {
|
||||||
self.symbol_table.debug();
|
self.symbol_table.debug();
|
||||||
println!("Namedstruct name {} id: {}", name, name.id);
|
|
||||||
let symbol = self.symbol_table.lookup_symbol(&name.id).unwrap();
|
let symbol = self.symbol_table.lookup_symbol(&name.id).unwrap();
|
||||||
let (tag, type_id) = match symbol.spec() {
|
let (tag, type_id) = match symbol.spec() {
|
||||||
SymbolSpec::RecordConstructor { tag, members: _, type_id } => (tag, type_id),
|
SymbolSpec::RecordConstructor { tag, members: _, type_id } => (tag, type_id),
|
||||||
e => return Expression::ReductionError(format!("Bad symbol for NamedStruct: {:?}", e)),
|
e => return Expression::ReductionError(format!("Bad symbol for NamedStruct: {:?}", e)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let field_order = compute_field_orderings(&self.type_context, &type_id, tag).unwrap();
|
// Eventually, the ReducedIR should decide what field ordering is optimal.
|
||||||
|
// For now, just do it alphabetically.
|
||||||
|
let mut field_order: Vec<String> = self
|
||||||
|
.type_context
|
||||||
|
.lookup_record_members(&type_id, tag)
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.map(|(field, _type_id)| field)
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
field_order.sort_unstable();
|
||||||
|
|
||||||
let mut field_map = HashMap::new();
|
let mut field_map = HashMap::new();
|
||||||
for (name, expr) in fields.iter() {
|
for (name, expr) in fields.iter() {
|
||||||
@ -170,8 +179,6 @@ impl<'a, 'b> Reducer<'a, 'b> {
|
|||||||
WhileExpression { .. } => Expression::ReductionError("While expr not implemented".to_string()),
|
WhileExpression { .. } => Expression::ReductionError("While expr not implemented".to_string()),
|
||||||
ForExpression { .. } => Expression::ReductionError("For expr not implemented".to_string()),
|
ForExpression { .. } => Expression::ReductionError("For expr not implemented".to_string()),
|
||||||
ListLiteral { .. } => Expression::ReductionError("ListLiteral expr not implemented".to_string()),
|
ListLiteral { .. } => Expression::ReductionError("ListLiteral expr not implemented".to_string()),
|
||||||
Access { name, expr } =>
|
|
||||||
Expression::Access { name: name.as_ref().to_string(), expr: Box::new(self.expression(expr)) },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,21 +388,3 @@ impl ast::Pattern {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given the type context and a variant, compute what order the fields on it were stored.
|
|
||||||
/// This needs to be public until type-checking is fully implemented because the type information
|
|
||||||
/// is only available at runtime.
|
|
||||||
pub fn compute_field_orderings(
|
|
||||||
type_context: &TypeContext,
|
|
||||||
type_id: &TypeId,
|
|
||||||
tag: u32,
|
|
||||||
) -> Option<Vec<String>> {
|
|
||||||
// Eventually, the ReducedIR should decide what field ordering is optimal.
|
|
||||||
// For now, just do it alphabetically.
|
|
||||||
|
|
||||||
let record_members = type_context.lookup_record_members(type_id, tag)?;
|
|
||||||
let mut field_order: Vec<String> =
|
|
||||||
record_members.iter().map(|(field, _type_id)| field).cloned().collect();
|
|
||||||
field_order.sort_unstable();
|
|
||||||
Some(field_order)
|
|
||||||
}
|
|
||||||
|
@ -50,7 +50,6 @@ pub enum Expression {
|
|||||||
Tuple(Vec<Expression>),
|
Tuple(Vec<Expression>),
|
||||||
Lookup(Lookup),
|
Lookup(Lookup),
|
||||||
Assign { lval: DefId, rval: Box<Expression> },
|
Assign { lval: DefId, rval: Box<Expression> },
|
||||||
Access { name: String, expr: Box<Expression> },
|
|
||||||
Callable(Callable),
|
Callable(Callable),
|
||||||
Call { f: Box<Expression>, args: Vec<Expression> },
|
Call { f: Box<Expression>, args: Vec<Expression> },
|
||||||
Conditional { cond: Box<Expression>, then_clause: Vec<Statement>, else_clause: Vec<Statement> },
|
Conditional { cond: Box<Expression>, then_clause: Vec<Statement>, else_clause: Vec<Statement> },
|
||||||
|
@ -126,28 +126,6 @@ impl<'a, 'b> Evaluator<'a, 'b> {
|
|||||||
Expression::CaseMatch { box cond, alternatives } =>
|
Expression::CaseMatch { box cond, alternatives } =>
|
||||||
self.case_match_expression(cond, alternatives)?,
|
self.case_match_expression(cond, alternatives)?,
|
||||||
Expression::ReductionError(e) => return Err(e.into()),
|
Expression::ReductionError(e) => return Err(e.into()),
|
||||||
Expression::Access { name, box expr } => {
|
|
||||||
let expr = self.expression(expr)?;
|
|
||||||
match expr {
|
|
||||||
Primitive::Object { items, ordered_fields: Some(ordered_fields), .. } => {
|
|
||||||
let idx = match ordered_fields.iter().position(|s| s == &name) {
|
|
||||||
Some(idx) => idx,
|
|
||||||
None => return Err(format!("Field `{}` not found", name).into()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let item = match items.get(idx) {
|
|
||||||
Some(item) => item,
|
|
||||||
None => return Err(format!("Field lookup `{}` failed", name).into()),
|
|
||||||
};
|
|
||||||
|
|
||||||
item.clone()
|
|
||||||
}
|
|
||||||
e =>
|
|
||||||
return Err(
|
|
||||||
format!("Trying to do a field lookup on a non-object value: {:?}", e).into()
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#![cfg(test)]
|
#![cfg(test)]
|
||||||
use pretty_assertions::assert_eq;
|
|
||||||
use test_case::test_case;
|
use test_case::test_case;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
symbol_table::SymbolTable,
|
symbol_table::SymbolTable,
|
||||||
@ -367,14 +367,3 @@ import Option::*
|
|||||||
let x = Some(9); if x is Some(q) then { q } else { 0 }"#;
|
let x = Some(9); if x is Some(q) then { q } else { 0 }"#;
|
||||||
eval_assert(source, "9");
|
eval_assert(source, "9");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn accessors() {
|
|
||||||
let source = r#"
|
|
||||||
type Klewos = Klewos { a: Int, b: String }
|
|
||||||
let value = Klewos::Klewos { a: 50, b: "nah" }
|
|
||||||
(value.a, value.b)
|
|
||||||
"#;
|
|
||||||
|
|
||||||
eval_assert(source, r#"(50, "nah")"#);
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user