Code gardening.
This commit is contained in:
parent
b52e236c67
commit
811776d9e7
15 changed files with 245 additions and 90 deletions
|
@ -33,6 +33,10 @@ impl Block {
|
||||||
self.ir
|
self.ir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ir_ref(&self) -> Vec<&IR> {
|
||||||
|
self.ir.iter().collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.ir.is_empty()
|
self.ir.is_empty()
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,21 @@ pub struct Context {
|
||||||
impl Context {
|
impl Context {
|
||||||
/// Declare an anonymous trait as an aggregate of other types.
|
/// Declare an anonymous trait as an aggregate of other types.
|
||||||
pub fn anonymous_trait(&mut self, requirements: Vec<TyIdx>, location: Location) -> TyIdx {
|
pub fn anonymous_trait(&mut self, requirements: Vec<TyIdx>, location: Location) -> TyIdx {
|
||||||
|
// If there's only one type in the requirement we can just return a reference to that instead.
|
||||||
|
if requirements.len() == 1 {
|
||||||
|
return requirements[0].clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's already an anonymous trait with the same dependencies then return a reference to that instead.
|
||||||
|
for (i, ty) in self.types.iter().enumerate() {
|
||||||
|
if ty.is_trait()
|
||||||
|
&& ty.is_anonymous()
|
||||||
|
&& ty.get_dependencies() == Some(requirements.iter().collect())
|
||||||
|
{
|
||||||
|
return i.into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let idx = self.types.len();
|
let idx = self.types.len();
|
||||||
let ty = Ty::new_trait(None, location, requirements);
|
let ty = Ty::new_trait(None, location, requirements);
|
||||||
self.types.push(ty);
|
self.types.push(ty);
|
||||||
|
@ -114,7 +129,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve a specific block by it's index.
|
/// Retrieve a specific block by it's index.
|
||||||
pub fn get_block(&self, idx: BlockIdx) -> Option<&Block> {
|
pub fn get_block(&self, idx: &BlockIdx) -> Option<&Block> {
|
||||||
self.blocks.get(usize::from(idx))
|
self.blocks.get(usize::from(idx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,18 @@ impl CompileError {
|
||||||
kind,
|
kind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn message(&self) -> &str {
|
||||||
|
&self.message
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn location(&self) -> &Location {
|
||||||
|
&self.location
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kind(&self) -> &ErrorKind {
|
||||||
|
&self.kind
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for CompileError {
|
impl fmt::Display for CompileError {
|
||||||
|
|
|
@ -26,6 +26,14 @@ impl Function {
|
||||||
self.clauses.push(Clause::new(arguments, block));
|
self.clauses.push(Clause::new(arguments, block));
|
||||||
idx.into()
|
idx.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clauses(&self) -> Vec<&Clause> {
|
||||||
|
self.clauses.iter().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn return_type(&self) -> &TyIdx {
|
||||||
|
&self.return_type
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -42,6 +50,14 @@ impl Clause {
|
||||||
});
|
});
|
||||||
Clause { arguments, body }
|
Clause { arguments, body }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn arguments(&self) -> Vec<(&StringIdx, &TyIdx)> {
|
||||||
|
self.arguments.iter().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn body(&self) -> &BlockIdx {
|
||||||
|
&self.body
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
|
|
@ -28,7 +28,11 @@ pub fn pass(ir: &mut IR, context: &mut Context) {
|
||||||
BinOp::ShiftRight => "shift_right",
|
BinOp::ShiftRight => "shift_right",
|
||||||
};
|
};
|
||||||
let method_name = context.constant_string(method_name);
|
let method_name = context.constant_string(method_name);
|
||||||
ir.kind = IRKind::MethodCall(Box::new(lhs.clone()), method_name, vec![rhs.clone()]);
|
ir.set_kind(IRKind::MethodCall(
|
||||||
|
Box::new(lhs.clone()),
|
||||||
|
method_name,
|
||||||
|
vec![rhs.clone()],
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,11 @@ pub fn pass(ir: &mut IR, context: &mut Context) {
|
||||||
UnOp::Plus => "unary_plus",
|
UnOp::Plus => "unary_plus",
|
||||||
};
|
};
|
||||||
let method_name = context.constant_string(method_name);
|
let method_name = context.constant_string(method_name);
|
||||||
ir.kind = IRKind::MethodCall(Box::new(rhs.clone()), method_name, Vec::default());
|
ir.set_kind(IRKind::MethodCall(
|
||||||
|
Box::new(rhs.clone()),
|
||||||
|
method_name,
|
||||||
|
Vec::default(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::ir::{IRKind, Val, IR};
|
use crate::ir::{IRKind, Val, IR};
|
||||||
use huia_parser::ast::binary::Operator as BinOp;
|
use huia_parser::ast::binary::Operator as BinOp;
|
||||||
use huia_parser::ast::unary::Operator as UnOp;
|
|
||||||
use std::f64;
|
use std::f64;
|
||||||
|
|
||||||
/// Perform constant folding on the provided node, or not.
|
/// Perform constant folding on the provided node, or not.
|
||||||
|
@ -22,7 +21,7 @@ pub fn pass(ir: &mut IR, context: &mut Context) {
|
||||||
if let Some(value) = value {
|
if let Some(value) = value {
|
||||||
ir.set_kind(IRKind::Constant(Val::Integer(value)));
|
ir.set_kind(IRKind::Constant(Val::Integer(value)));
|
||||||
let idx = context.constant_string("Huia.Native.Integer");
|
let idx = context.constant_string("Huia.Native.Integer");
|
||||||
ir.set_result_type(context.reference_type(&idx, ir.location.clone()));
|
ir.set_result_type(context.reference_type(&idx, ir.get_location().clone()));
|
||||||
}
|
}
|
||||||
} else if lhs.is_float() && rhs.is_float() {
|
} else if lhs.is_float() && rhs.is_float() {
|
||||||
let lhs = lhs.float().unwrap();
|
let lhs = lhs.float().unwrap();
|
||||||
|
@ -31,47 +30,7 @@ pub fn pass(ir: &mut IR, context: &mut Context) {
|
||||||
if let Some(value) = value {
|
if let Some(value) = value {
|
||||||
ir.set_kind(IRKind::Constant(Val::Float(value)));
|
ir.set_kind(IRKind::Constant(Val::Float(value)));
|
||||||
let idx = context.constant_string("Huia.Native.Float");
|
let idx = context.constant_string("Huia.Native.Float");
|
||||||
ir.set_result_type(context.reference_type(&idx, ir.location.clone()));
|
ir.set_result_type(context.reference_type(&idx, ir.get_location().clone()));
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ir.is_unary() {
|
|
||||||
let (op, rhs) = ir.get_unary().unwrap();
|
|
||||||
if !rhs.is_constant() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let rhs = rhs.get_value().unwrap();
|
|
||||||
|
|
||||||
match op {
|
|
||||||
UnOp::LogicalNot => {
|
|
||||||
if rhs.is_boolean() {
|
|
||||||
// if the RHS is a boolean constant then fold it.
|
|
||||||
let value = rhs.boolean().unwrap();
|
|
||||||
ir.set_kind(IRKind::Constant(Val::Boolean(!value)));
|
|
||||||
} else {
|
|
||||||
// otherwise just return false for all other constant values.
|
|
||||||
ir.set_kind(IRKind::Constant(Val::Boolean(false)));
|
|
||||||
}
|
|
||||||
let tyname = context.constant_string("Huia.Native.Boolean");
|
|
||||||
let ty = context.reference_type(&tyname, ir.location.clone());
|
|
||||||
ir.set_result_type(ty)
|
|
||||||
}
|
|
||||||
UnOp::Minus => {
|
|
||||||
if rhs.is_integer() {
|
|
||||||
let value = rhs.integer().unwrap();
|
|
||||||
ir.set_kind(IRKind::Constant(Val::Integer(-value)));
|
|
||||||
} else if rhs.is_float() {
|
|
||||||
let value = rhs.float().unwrap();
|
|
||||||
ir.set_kind(IRKind::Constant(Val::Float(-value)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UnOp::Plus => {
|
|
||||||
if rhs.is_integer() {
|
|
||||||
let value = rhs.integer().unwrap();
|
|
||||||
ir.set_kind(IRKind::Constant(Val::Integer(value)));
|
|
||||||
} else if rhs.is_float() {
|
|
||||||
let value = rhs.float().unwrap();
|
|
||||||
ir.set_kind(IRKind::Constant(Val::Float(value)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,21 +97,4 @@ mod test {
|
||||||
assert!(ir.is_constant());
|
assert!(ir.is_constant());
|
||||||
assert!(ir.get_value().unwrap().float().unwrap() - 1.0 < f64::EPSILON);
|
assert!(ir.get_value().unwrap().float().unwrap() - 1.0 < f64::EPSILON);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn integer_unary_folding() {
|
|
||||||
let term = Term::input("!3").unwrap()[0].clone();
|
|
||||||
let mut context = Context::test();
|
|
||||||
let mut builder = Builder::default();
|
|
||||||
|
|
||||||
builder.build(term, &mut context);
|
|
||||||
let mut ir = builder.pop_ir().unwrap();
|
|
||||||
ir.improve(&mut context, pass);
|
|
||||||
|
|
||||||
assert!(ir.is_constant());
|
|
||||||
assert!(!ir.get_value().unwrap().boolean().unwrap());
|
|
||||||
|
|
||||||
let ty = context.get_type(&ir.result_type()).unwrap();
|
|
||||||
assert!(ty.is_native_boolean());
|
|
||||||
}
|
|
||||||
}
|
}
|
4
huia-compiler/src/improvements/mod.rs
Normal file
4
huia-compiler/src/improvements/mod.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
pub mod desugar_infix;
|
||||||
|
pub mod desugar_unary;
|
||||||
|
pub mod infix_folding;
|
||||||
|
pub mod unary_folding;
|
72
huia-compiler/src/improvements/unary_folding.rs
Normal file
72
huia-compiler/src/improvements/unary_folding.rs
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
use crate::context::Context;
|
||||||
|
use crate::ir::{IRKind, Val, IR};
|
||||||
|
use huia_parser::ast::unary::Operator as UnOp;
|
||||||
|
|
||||||
|
/// Perform constant folding on the provided node, or not.
|
||||||
|
pub fn pass(ir: &mut IR, context: &mut Context) {
|
||||||
|
if ir.is_unary() {
|
||||||
|
let (op, rhs) = ir.get_unary().unwrap();
|
||||||
|
if !rhs.is_constant() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let rhs = rhs.get_value().unwrap();
|
||||||
|
|
||||||
|
match op {
|
||||||
|
UnOp::LogicalNot => {
|
||||||
|
if rhs.is_boolean() {
|
||||||
|
// if the RHS is a boolean constant then fold it.
|
||||||
|
let value = rhs.boolean().unwrap();
|
||||||
|
ir.set_kind(IRKind::Constant(Val::Boolean(!value)));
|
||||||
|
} else {
|
||||||
|
// otherwise just return false for all other constant values.
|
||||||
|
ir.set_kind(IRKind::Constant(Val::Boolean(false)));
|
||||||
|
}
|
||||||
|
let tyname = context.constant_string("Huia.Native.Boolean");
|
||||||
|
let ty = context.reference_type(&tyname, ir.get_location().clone());
|
||||||
|
ir.set_result_type(ty)
|
||||||
|
}
|
||||||
|
UnOp::Minus => {
|
||||||
|
if rhs.is_integer() {
|
||||||
|
let value = rhs.integer().unwrap();
|
||||||
|
ir.set_kind(IRKind::Constant(Val::Integer(-value)));
|
||||||
|
} else if rhs.is_float() {
|
||||||
|
let value = rhs.float().unwrap();
|
||||||
|
ir.set_kind(IRKind::Constant(Val::Float(-value)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnOp::Plus => {
|
||||||
|
if rhs.is_integer() {
|
||||||
|
let value = rhs.integer().unwrap();
|
||||||
|
ir.set_kind(IRKind::Constant(Val::Integer(value)));
|
||||||
|
} else if rhs.is_float() {
|
||||||
|
let value = rhs.float().unwrap();
|
||||||
|
ir.set_kind(IRKind::Constant(Val::Float(value)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use crate::ir::builder::Builder;
|
||||||
|
use huia_parser::ast::Term;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn integer_unary_folding() {
|
||||||
|
let term = Term::input("!3").unwrap()[0].clone();
|
||||||
|
let mut context = Context::test();
|
||||||
|
let mut builder = Builder::default();
|
||||||
|
|
||||||
|
builder.build(term, &mut context);
|
||||||
|
let mut ir = builder.pop_ir().unwrap();
|
||||||
|
ir.improve(&mut context, pass);
|
||||||
|
|
||||||
|
assert!(ir.is_constant());
|
||||||
|
assert!(!ir.get_value().unwrap().boolean().unwrap());
|
||||||
|
|
||||||
|
let ty = context.get_type(&ir.result_type()).unwrap();
|
||||||
|
assert!(ty.is_native_boolean());
|
||||||
|
}
|
||||||
|
}
|
|
@ -570,6 +570,7 @@ impl Builder {
|
||||||
|
|
||||||
let ty = context.declare_trait(&ty_idx, types, location);
|
let ty = context.declare_trait(&ty_idx, types, location);
|
||||||
self.push_ty(ty.clone());
|
self.push_ty(ty.clone());
|
||||||
|
self.push_block();
|
||||||
|
|
||||||
for node in body {
|
for node in body {
|
||||||
self.build(node.clone(), &mut context);
|
self.build(node.clone(), &mut context);
|
||||||
|
@ -827,7 +828,6 @@ mod test {
|
||||||
let ir = builder.pop_ir().unwrap();
|
let ir = builder.pop_ir().unwrap();
|
||||||
assert!(ir.is_jump_if_true());
|
assert!(ir.is_jump_if_true());
|
||||||
let block = builder.pop_block().unwrap();
|
let block = builder.pop_block().unwrap();
|
||||||
println!("Block: {:?}", block);
|
|
||||||
assert!(block.is_empty());
|
assert!(block.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -849,7 +849,7 @@ mod test {
|
||||||
let mut context = Context::test();
|
let mut context = Context::test();
|
||||||
builder.build(term, &mut context);
|
builder.build(term, &mut context);
|
||||||
let ir = builder.pop_ir().unwrap();
|
let ir = builder.pop_ir().unwrap();
|
||||||
assert!(ir.is_constuctor());
|
assert!(ir.is_constructor());
|
||||||
assert!(context.find_type("Delorean").is_some());
|
assert!(context.find_type("Delorean").is_some());
|
||||||
assert!(context.find_type("Huia.Native.Integer").is_some());
|
assert!(context.find_type("Huia.Native.Integer").is_some());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
pub mod builder;
|
pub mod builder;
|
||||||
pub mod constant_folding;
|
|
||||||
pub mod desugar_infix;
|
|
||||||
pub mod desugar_unary;
|
|
||||||
|
|
||||||
use crate::block::BlockIdx;
|
use crate::block::BlockIdx;
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
|
@ -28,6 +25,13 @@ impl IR {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_call(&self) -> Option<(&IR, &Vec<IR>)> {
|
||||||
|
match self.kind {
|
||||||
|
IRKind::Call(ref ir, ref args) => Some((ir, args)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_infix(&self) -> Option<(&BinOp, &IR, &IR)> {
|
pub fn get_infix(&self) -> Option<(&BinOp, &IR, &IR)> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
IRKind::Infix(ref op, ref lhs, ref rhs) => Some((op, lhs, rhs)),
|
IRKind::Infix(ref op, ref lhs, ref rhs) => Some((op, lhs, rhs)),
|
||||||
|
@ -35,6 +39,14 @@ impl IR {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_kind(&self) -> &IRKind {
|
||||||
|
&self.kind
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_location(&self) -> &Location {
|
||||||
|
&self.location
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_unary(&self) -> Option<(&UnOp, &IR)> {
|
pub fn get_unary(&self) -> Option<(&UnOp, &IR)> {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
IRKind::Unary(ref op, ref rhs) => Some((op, rhs)),
|
IRKind::Unary(ref op, ref rhs) => Some((op, rhs)),
|
||||||
|
@ -142,7 +154,7 @@ impl IR {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_constuctor(&self) -> bool {
|
pub fn is_constructor(&self) -> bool {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
IRKind::Constructor(..) => true,
|
IRKind::Constructor(..) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -427,13 +439,13 @@ pub enum IRKind {
|
||||||
/// A constant value.
|
/// A constant value.
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum Val {
|
pub enum Val {
|
||||||
|
Array(Vec<IR>),
|
||||||
Atom(StringIdx),
|
Atom(StringIdx),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Float(f64),
|
Float(f64),
|
||||||
Integer(i64),
|
Integer(i64),
|
||||||
String(StringIdx),
|
|
||||||
Array(Vec<IR>),
|
|
||||||
Map(Vec<(IR, IR)>),
|
Map(Vec<(IR, IR)>),
|
||||||
|
String(StringIdx),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Val {
|
impl Val {
|
||||||
|
@ -444,6 +456,13 @@ impl Val {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn atom(&self) -> Option<&StringIdx> {
|
||||||
|
match self {
|
||||||
|
Val::Atom(ref atom) => Some(atom),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn boolean(&self) -> Option<bool> {
|
pub fn boolean(&self) -> Option<bool> {
|
||||||
match self {
|
match self {
|
||||||
Val::Boolean(ref value) => Some(*value),
|
Val::Boolean(ref value) => Some(*value),
|
||||||
|
@ -465,6 +484,13 @@ impl Val {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_array(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Val::Array(..) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_atom(&self) -> bool {
|
pub fn is_atom(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Val::Atom(..) => true,
|
Val::Atom(..) => true,
|
||||||
|
@ -493,18 +519,6 @@ impl Val {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_string(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
Val::String(..) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn is_array(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
Val::Array(..) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn is_map(&self) -> bool {
|
pub fn is_map(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Val::Map(..) => true,
|
Val::Map(..) => true,
|
||||||
|
@ -512,6 +526,13 @@ impl Val {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_string(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Val::String(..) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn map(&self) -> Option<Vec<&(IR, IR)>> {
|
pub fn map(&self) -> Option<Vec<&(IR, IR)>> {
|
||||||
match self {
|
match self {
|
||||||
Val::Map(ref elements) => Some(elements.iter().collect()),
|
Val::Map(ref elements) => Some(elements.iter().collect()),
|
||||||
|
|
|
@ -3,6 +3,7 @@ mod context;
|
||||||
mod env;
|
mod env;
|
||||||
mod error;
|
mod error;
|
||||||
mod function;
|
mod function;
|
||||||
|
mod improvements;
|
||||||
mod ir;
|
mod ir;
|
||||||
mod location;
|
mod location;
|
||||||
mod method;
|
mod method;
|
||||||
|
@ -24,9 +25,10 @@ pub fn compile_file(path: &str) -> Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
context.improve_ir(|mut ir, mut context| {
|
context.improve_ir(|mut ir, mut context| {
|
||||||
ir::constant_folding::pass(&mut ir, &mut context);
|
improvements::infix_folding::pass(&mut ir, &mut context);
|
||||||
ir::desugar_infix::pass(&mut ir, &mut context);
|
improvements::unary_folding::pass(&mut ir, &mut context);
|
||||||
ir::desugar_unary::pass(&mut ir, &mut context);
|
improvements::desugar_infix::pass(&mut ir, &mut context);
|
||||||
|
improvements::desugar_unary::pass(&mut ir, &mut context);
|
||||||
});
|
});
|
||||||
|
|
||||||
context
|
context
|
||||||
|
|
|
@ -17,6 +17,13 @@ pub struct Ty {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ty {
|
impl Ty {
|
||||||
|
pub fn get_dependencies(&self) -> Option<Vec<&TyIdx>> {
|
||||||
|
match self.inner {
|
||||||
|
TyInner::Trait { ref dependencies } => Some(dependencies.iter().collect()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_prop_type(&self, name: &StringIdx) -> Option<&TyIdx> {
|
pub fn get_prop_type(&self, name: &StringIdx) -> Option<&TyIdx> {
|
||||||
match self.inner {
|
match self.inner {
|
||||||
TyInner::Type { ref properties } => properties.get(name),
|
TyInner::Type { ref properties } => properties.get(name),
|
||||||
|
@ -24,6 +31,20 @@ impl Ty {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_properties(&self) -> Option<Vec<(&StringIdx, &TyIdx)>> {
|
||||||
|
match self.inner {
|
||||||
|
TyInner::Type { ref properties } => Some(properties.iter().collect()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_anonymous(&self) -> bool {
|
||||||
|
match self.name {
|
||||||
|
None => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_impl(&self) -> bool {
|
pub fn is_impl(&self) -> bool {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
TyKind::Impl => true,
|
TyKind::Impl => true,
|
||||||
|
@ -31,6 +52,20 @@ impl Ty {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_native_array(&self) -> bool {
|
||||||
|
match self.inner {
|
||||||
|
TyInner::NativeArray => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_native_atom(&self) -> bool {
|
||||||
|
match self.inner {
|
||||||
|
TyInner::NativeAtom => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_native_boolean(&self) -> bool {
|
pub fn is_native_boolean(&self) -> bool {
|
||||||
match self.inner {
|
match self.inner {
|
||||||
TyInner::NativeBoolean => true,
|
TyInner::NativeBoolean => true,
|
||||||
|
@ -38,6 +73,34 @@ impl Ty {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_native_float(&self) -> bool {
|
||||||
|
match self.inner {
|
||||||
|
TyInner::NativeFloat => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_native_integer(&self) -> bool {
|
||||||
|
match self.inner {
|
||||||
|
TyInner::NativeInteger => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_native_map(&self) -> bool {
|
||||||
|
match self.inner {
|
||||||
|
TyInner::NativeMap => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_native_string(&self) -> bool {
|
||||||
|
match self.inner {
|
||||||
|
TyInner::NativeString => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_unresolved(&self) -> bool {
|
pub fn is_unresolved(&self) -> bool {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
TyKind::Unresolved => true,
|
TyKind::Unresolved => true,
|
||||||
|
|
|
@ -67,14 +67,12 @@ impl<'a> From<Pair<'a, Rule>> for Clause {
|
||||||
fn from(pair: Pair<'a, Rule>) -> Self {
|
fn from(pair: Pair<'a, Rule>) -> Self {
|
||||||
match pair.as_rule() {
|
match pair.as_rule() {
|
||||||
Rule::function_clause => {
|
Rule::function_clause => {
|
||||||
println!("clause = {:#?}", pair);
|
|
||||||
let mut inner = pair.clone().into_inner();
|
let mut inner = pair.clone().into_inner();
|
||||||
let arguments = inner
|
let arguments = inner
|
||||||
.next()
|
.next()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_inner()
|
.into_inner()
|
||||||
.map(|p| {
|
.map(|p| {
|
||||||
println!("p = {:?}", p);
|
|
||||||
let mut inner = p.into_inner();
|
let mut inner = p.into_inner();
|
||||||
let keyword = Identifier::from(inner.next().unwrap());
|
let keyword = Identifier::from(inner.next().unwrap());
|
||||||
let typespec = TypeSpec::from(inner.next().unwrap());
|
let typespec = TypeSpec::from(inner.next().unwrap());
|
||||||
|
|
|
@ -1119,8 +1119,6 @@ mod test {
|
||||||
fn test_if_else() {
|
fn test_if_else() {
|
||||||
let terms = Term::input(" if true do 123 else 456 end ").unwrap();
|
let terms = Term::input(" if true do 123 else 456 end ").unwrap();
|
||||||
let (_test, positive, negative) = terms[0].if_expr().unwrap();
|
let (_test, positive, negative) = terms[0].if_expr().unwrap();
|
||||||
println!("positive: {:?}", positive);
|
|
||||||
println!("negative: {:?}", negative);
|
|
||||||
assert_eq!(positive.len(), 1);
|
assert_eq!(positive.len(), 1);
|
||||||
assert_eq!(negative.len(), 1);
|
assert_eq!(negative.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue