Merge pull request #428 from developedby/experimental

feat: Undo native U1120, partially add F60, refactor
This commit is contained in:
Felipe G 2022-11-30 13:57:37 -03:00 committed by GitHub
commit 20f1cc43ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 404 additions and 807 deletions

View File

@ -1 +0,0 @@
K

View File

@ -119,7 +119,7 @@ fn desugar_str(input: &str, range: Range) -> Box<desugared::Expr> {
desugared::Expr::ctr( desugared::Expr::ctr(
range, range,
cons.clone(), cons.clone(),
vec![desugared::Expr::num60(range, chr as u64), right], vec![desugared::Expr::num_u60(range, chr as u64), right],
) )
}) })
} }
@ -152,25 +152,11 @@ fn codegen_all_expr(
eval_ctr(quote, TermTag::Typ), eval_ctr(quote, TermTag::Typ),
vec![range_to_num(expr.range)], vec![range_to_num(expr.range)],
), ),
NumType { NumTypeU60 => mk_lifted_ctr(
typ: kind_tree::NumType::U60,
} => mk_lifted_ctr(
eval_ctr(quote, TermTag::U60), eval_ctr(quote, TermTag::U60),
vec![range_to_num(expr.range)], vec![range_to_num(expr.range)],
), ),
NumType { NumTypeF60 => todo!(),
typ: kind_tree::NumType::U120,
} => mk_lifted_ctr(
eval_ctr(quote, TermTag::Ctr(0)),
vec![
mk_ctr_name_from_str("U120"),
if lhs {
mk_var("orig")
} else {
range_to_num(expr.range)
},
],
),
Var { name } => { Var { name } => {
if quote && !lhs { if quote && !lhs {
set_origin(name) set_origin(name)
@ -292,28 +278,11 @@ fn codegen_all_expr(
codegen_all_expr(lhs_rule, lhs, num, quote, expr), codegen_all_expr(lhs_rule, lhs, num, quote, expr),
], ],
), ),
Num { NumU60 { numb } => mk_lifted_ctr(
num: kind_tree::Number::U60(n),
} => mk_lifted_ctr(
eval_ctr(quote, TermTag::Num), eval_ctr(quote, TermTag::Num),
vec![range_to_num(expr.range), mk_u60(*n)], vec![range_to_num(expr.range), mk_u60(*numb)],
), ),
Num { NumF60 { numb: _ } => todo!(),
num: kind_tree::Number::U120(numb),
} => {
let new = QualifiedIdent::new_static("U120.new", None, expr.range);
let expr = desugared::Expr::ctr(
expr.range,
new,
vec![
desugared::Expr::num60(expr.range, (numb >> 60) as u64),
desugared::Expr::num60(expr.range, (numb & 0xFFFFFFFFFFFFFFF) as u64),
],
);
codegen_all_expr(lhs_rule, lhs, num, quote, &expr)
}
Binary { op, left, right } => mk_lifted_ctr( Binary { op, left, right } => mk_lifted_ctr(
eval_ctr(quote, TermTag::Binary), eval_ctr(quote, TermTag::Binary),
vec![ vec![

View File

@ -4,7 +4,7 @@
use kind_span::{EncodedRange, Range}; use kind_span::{EncodedRange, Range};
use kind_tree::backend::Term; use kind_tree::backend::Term;
use kind_tree::symbol::{Ident, QualifiedIdent}; use kind_tree::symbol::{Ident, QualifiedIdent};
use kind_tree::{desugared, Number, Operator}; use kind_tree::{desugared, Operator};
use crate::errors::TypeError; use crate::errors::TypeError;
use desugared::Expr; use desugared::Expr;
@ -142,25 +142,7 @@ fn parse_all_expr(
for arg in parse_list(&args[2])? { for arg in parse_list(&args[2])? {
res.push(parse_all_expr(names.clone(), &arg)?); res.push(parse_all_expr(names.clone(), &arg)?);
} }
Ok(Expr::ctr(orig, name, res))
if name.to_str() == "U120.new" && res.len() == 2 {
match (&res[0].data, &res[1].data) {
(
desugared::ExprKind::Num {
num: Number::U60(hi),
},
desugared::ExprKind::Num {
num: Number::U60(lo),
},
) => {
let num = (*hi as u128) << 60 | *lo as u128;
Ok(Expr::num120(orig, num))
}
_ => Ok(Expr::ctr(orig, name, res)),
}
} else {
Ok(Expr::ctr(orig, name, res))
}
} }
"Kind.Term.Quoted.fun" => Ok(Expr::fun( "Kind.Term.Quoted.fun" => Ok(Expr::fun(
parse_orig(&args[1])?, parse_orig(&args[1])?,
@ -174,8 +156,9 @@ fn parse_all_expr(
}, },
)), )),
"Kind.Term.Quoted.hlp" => Ok(Expr::hlp(parse_orig(&args[0])?, Ident::generate("?"))), "Kind.Term.Quoted.hlp" => Ok(Expr::hlp(parse_orig(&args[0])?, Ident::generate("?"))),
"Kind.Term.Quoted.u60" => Ok(Expr::u60(parse_orig(&args[0])?)), "Kind.Term.Quoted.u60" => Ok(Expr::type_u60(parse_orig(&args[0])?)),
"Kind.Term.Quoted.num" => Ok(Expr::num60(parse_orig(&args[0])?, parse_num(&args[1])?)), // TODO: do something about u120? "Kind.Term.Quoted.num" => Ok(Expr::num_u60(parse_orig(&args[0])?, parse_num(&args[1])?)),
// TODO: Change quoting to support floats
"Kind.Term.Quoted.op2" => Ok(Expr::binary( "Kind.Term.Quoted.op2" => Ok(Expr::binary(
parse_orig(&args[0])?, parse_orig(&args[0])?,
parse_op(&args[1])?, parse_op(&args[1])?,

View File

@ -78,7 +78,9 @@ impl<'a> Visitor for Subst<'a> {
match &mut pat.data { match &mut pat.data {
PatKind::Var(ident) => self.visit_pat_ident(ident), PatKind::Var(ident) => self.visit_pat_ident(ident),
PatKind::Str(_) => (), PatKind::Str(_) => (),
PatKind::Num(_) => (), PatKind::U60(_) => (),
PatKind::U120(_) => (),
PatKind::F60(_) => (),
PatKind::Char(_) => (), PatKind::Char(_) => (),
PatKind::Hole => (), PatKind::Hole => (),
PatKind::List(ls) => { PatKind::List(ls) => {

View File

@ -1,7 +1,7 @@
use kind_span::{Locatable, Range}; use kind_span::{Locatable, Range};
use kind_tree::concrete::expr::*; use kind_tree::concrete::expr::*;
use kind_tree::symbol::{Ident, QualifiedIdent}; use kind_tree::symbol::{Ident, QualifiedIdent};
use kind_tree::{NumType, Number, Operator}; use kind_tree::Operator;
use crate::errors::SyntaxDiagnostic; use crate::errors::SyntaxDiagnostic;
use crate::lexer::tokens::Token; use crate::lexer::tokens::Token;
@ -238,10 +238,10 @@ impl<'a> Parser<'a> {
let data = match id.to_string().as_str() { let data = match id.to_string().as_str() {
"Type" => ExprKind::Lit { lit: Literal::Type }, "Type" => ExprKind::Lit { lit: Literal::Type },
"U60" => ExprKind::Lit { "U60" => ExprKind::Lit {
lit: Literal::NumType(NumType::U60), lit: Literal::NumTypeU60,
}, },
"U120" => ExprKind::Lit { "F60" => ExprKind::Lit {
lit: Literal::NumType(NumType::U120), lit: Literal::NumTypeF60,
}, },
_ => ExprKind::Constr { _ => ExprKind::Constr {
name: id.clone(), name: id.clone(),
@ -260,10 +260,10 @@ impl<'a> Parser<'a> {
let data = match id.to_string().as_str() { let data = match id.to_string().as_str() {
"Type" => ExprKind::Lit { lit: Literal::Type }, "Type" => ExprKind::Lit { lit: Literal::Type },
"U60" => ExprKind::Lit { "U60" => ExprKind::Lit {
lit: Literal::NumType(NumType::U60), lit: Literal::NumTypeU60,
}, },
"U120" => ExprKind::Lit { "F60" => ExprKind::Lit {
lit: Literal::NumType(NumType::U120), lit: Literal::NumTypeF60,
}, },
_ => { _ => {
let (range_end, spine) = self.parse_call_tail(id.range, multiline)?; let (range_end, spine) = self.parse_call_tail(id.range, multiline)?;
@ -283,7 +283,7 @@ impl<'a> Parser<'a> {
Ok(Box::new(Expr { Ok(Box::new(Expr {
range, range,
data: ExprKind::Lit { data: ExprKind::Lit {
lit: Literal::Number(Number::U60(num)), lit: Literal::NumU60(num),
}, },
})) }))
} }
@ -294,7 +294,7 @@ impl<'a> Parser<'a> {
Ok(Box::new(Expr { Ok(Box::new(Expr {
range, range,
data: ExprKind::Lit { data: ExprKind::Lit {
lit: Literal::Number(Number::U120(num)), lit: Literal::NumU120(num),
}, },
})) }))
} }

View File

@ -25,21 +25,21 @@ impl<'a> Parser<'a> {
})) }))
} }
fn parse_pat_num60(&mut self) -> Result<Box<Pat>, SyntaxDiagnostic> { fn parse_pat_u60(&mut self) -> Result<Box<Pat>, SyntaxDiagnostic> {
let start = self.range(); let start = self.range();
let num = eat_single!(self, Token::Num60(n) => *n)?; let num = eat_single!(self, Token::Num60(n) => *n)?;
Ok(Box::new(Pat { Ok(Box::new(Pat {
range: start, range: start,
data: PatKind::Num(kind_tree::Number::U60(num)), data: PatKind::U60(num),
})) }))
} }
fn parse_pat_num120(&mut self) -> Result<Box<Pat>, SyntaxDiagnostic> { fn parse_pat_u120(&mut self) -> Result<Box<Pat>, SyntaxDiagnostic> {
let start = self.range(); let start = self.range();
let num = eat_single!(self, Token::Num120(n) => *n)?; let num = eat_single!(self, Token::Num120(n) => *n)?;
Ok(Box::new(Pat { Ok(Box::new(Pat {
range: start, range: start,
data: PatKind::Num(kind_tree::Number::U120(num)), data: PatKind::U120(num),
})) }))
} }
@ -132,9 +132,9 @@ impl<'a> Parser<'a> {
} else if self.get().is_str() { } else if self.get().is_str() {
self.parse_pat_str() self.parse_pat_str()
} else if self.get().is_num60() { } else if self.get().is_num60() {
self.parse_pat_num60() self.parse_pat_u60()
} else if self.get().is_num120() { } else if self.get().is_num120() {
self.parse_pat_num120() self.parse_pat_u120()
} else if self.check_actual(Token::LPar) { } else if self.check_actual(Token::LPar) {
self.parse_pat_group() self.parse_pat_group()
} else if self.get().is_lower_id() { } else if self.get().is_lower_id() {

View File

@ -23,7 +23,6 @@ impl<'a> DesugarState<'a> {
literal: &expr::Literal, literal: &expr::Literal,
) -> Box<desugared::Expr> { ) -> Box<desugared::Expr> {
match literal { match literal {
Literal::Number(kind_tree::Number::U120(num)) => desugared::Expr::num120(range, *num),
Literal::String(string) => { Literal::String(string) => {
if !self.check_implementation("String.cons", range, Sugar::String) if !self.check_implementation("String.cons", range, Sugar::String)
|| !self.check_implementation("String.nil", range, Sugar::String) || !self.check_implementation("String.nil", range, Sugar::String)
@ -34,10 +33,17 @@ impl<'a> DesugarState<'a> {
} }
Literal::Type => desugared::Expr::typ(range), Literal::Type => desugared::Expr::typ(range),
Literal::Help(name) => desugared::Expr::hlp(range, name.clone()), Literal::Help(name) => desugared::Expr::hlp(range, name.clone()),
Literal::NumType(kind_tree::NumType::U60) => desugared::Expr::u60(range), Literal::NumTypeU60 => desugared::Expr::type_u60(range),
Literal::NumType(kind_tree::NumType::U120) => desugared::Expr::u120(range), Literal::NumTypeF60 => desugared::Expr::type_f60(range),
Literal::Number(kind_tree::Number::U60(num)) => desugared::Expr::num60(range, *num), Literal::NumU60(num) => desugared::Expr::num_u60(range, *num),
Literal::Char(cht) => desugared::Expr::num60(range, *cht as u64), Literal::NumU120(num) => {
if !self.check_implementation("U120.new", range, Sugar::U120) {
return desugared::Expr::err(range);
}
desugared::Expr::num_u120(range, *num)
}
Literal::NumF60(num) => desugared::Expr::num_f60(range, *num),
Literal::Char(cht) => desugared::Expr::num_u60(range, *cht as u64),
} }
} }

View File

@ -291,9 +291,10 @@ impl<'a> DesugarState<'a> {
desugared::Expr::var(name) desugared::Expr::var(name)
} }
PatKind::Var(ident) => desugared::Expr::var(ident.0.clone()), PatKind::Var(ident) => desugared::Expr::var(ident.0.clone()),
PatKind::Num(kind_tree::Number::U60(n)) => desugared::Expr::num60(pat.range, *n), PatKind::U60(n) => desugared::Expr::num_u60(pat.range, *n),
PatKind::Char(n) => desugared::Expr::num60(pat.range, *n as u64), PatKind::U120(n) => desugared::Expr::num_u120(pat.range, *n),
PatKind::Num(kind_tree::Number::U120(n)) => desugared::Expr::num120(pat.range, *n), PatKind::F60(n) => desugared::Expr::num_f60(pat.range, *n),
PatKind::Char(n) => desugared::Expr::num_u60(pat.range, *n as u64),
PatKind::Pair(fst, snd) => self.desugar_pair_pat(pat.range, fst, snd), PatKind::Pair(fst, snd) => self.desugar_pair_pat(pat.range, fst, snd),
PatKind::List(ls) => self.desugar_list_pat(pat.range, ls), PatKind::List(ls) => self.desugar_list_pat(pat.range, ls),
PatKind::Str(string) => desugared::Expr::str(pat.range, string.to_owned()), PatKind::Str(string) => desugared::Expr::str(pat.range, string.to_owned()),

View File

@ -7,7 +7,6 @@ use kind_span::Range;
use kind_tree::desugared; use kind_tree::desugared;
use kind_tree::symbol::QualifiedIdent; use kind_tree::symbol::QualifiedIdent;
use kind_tree::untyped::{self}; use kind_tree::untyped::{self};
use kind_tree::Number;
use crate::errors::{PassError, GenericPassError}; use crate::errors::{PassError, GenericPassError};
@ -345,12 +344,8 @@ impl<'a> ErasureState<'a> {
untyped::Expr::ctr(expr.range, name.clone(), args) untyped::Expr::ctr(expr.range, name.clone(), args)
} }
Num { NumU60 { numb } => untyped::Expr::u60(expr.range, *numb),
num: Number::U60(num), NumF60 { numb } => untyped::Expr::f60(expr.range, *numb),
} => untyped::Expr::num60(expr.range, *num),
Num {
num: Number::U120(num),
} => untyped::Expr::num120(expr.range, *num),
Str { val } => { Str { val } => {
let nil = QualifiedIdent::new_static("String.nil", None, expr.range); let nil = QualifiedIdent::new_static("String.nil", None, expr.range);
let cons = QualifiedIdent::new_static("String.cons", None, expr.range); let cons = QualifiedIdent::new_static("String.cons", None, expr.range);
@ -488,12 +483,8 @@ impl<'a> ErasureState<'a> {
self.erase_expr(Ambient::Irrelevant, edge, typ); self.erase_expr(Ambient::Irrelevant, edge, typ);
expr expr
} }
Num { NumU60 { numb } => untyped::Expr::u60(expr.range, *numb),
num: Number::U60(num), NumF60 { numb } => untyped::Expr::f60(expr.range, *numb),
} => untyped::Expr::num60(expr.range, *num),
Num {
num: Number::U120(num),
} => untyped::Expr::num120(expr.range, *num),
Str { val } => { Str { val } => {
let nil = QualifiedIdent::new_static("String.nil", None, expr.range); let nil = QualifiedIdent::new_static("String.nil", None, expr.range);
let cons = QualifiedIdent::new_static("String.cons", None, expr.range); let cons = QualifiedIdent::new_static("String.cons", None, expr.range);
@ -516,7 +507,7 @@ impl<'a> ErasureState<'a> {
let right = self.erase_expr(ambient, edge, right); let right = self.erase_expr(ambient, edge, right);
untyped::Expr::binary(expr.range, *op, left, right) untyped::Expr::binary(expr.range, *op, left, right)
} }
Typ | NumType { typ: _ } | Hole { num: _ } | Hlp(_) | Err => { Typ | NumTypeU60 { .. } | NumTypeF60 { .. } | Hole { .. } | Hlp(_) | Err => {
if ambient != Ambient::Irrelevant { if ambient != Ambient::Irrelevant {
self.set_relevance(edge, Relevance::Irrelevant, expr.range); self.set_relevance(edge, Relevance::Irrelevant, expr.range);
} }

View File

@ -22,6 +22,7 @@ pub enum Sugar {
Pair, Pair,
BoolIf, BoolIf,
String, String,
U120,
Match(String), Match(String),
Open(String), Open(String),
} }
@ -215,6 +216,7 @@ impl Diagnostic for PassError {
Sugar::Pair => "You must implement 'Sigma' and 'Sigma.new' in order to use the sigma notation.".to_string(), Sugar::Pair => "You must implement 'Sigma' and 'Sigma.new' in order to use the sigma notation.".to_string(),
Sugar::BoolIf => "You must implement 'Bool.if' in order to use the if notation.".to_string(), Sugar::BoolIf => "You must implement 'Bool.if' in order to use the if notation.".to_string(),
Sugar::String => "You must implement 'String.cons' in order to use the string notation.".to_string(), Sugar::String => "You must implement 'String.cons' in order to use the string notation.".to_string(),
Sugar::U120 => "You must implement 'U120.new' in order to use the u120 notation.".to_string(),
Sugar::Match(name) => format!("You must implement '{}.match' in order to use the match notation (or derive match with #derive[match]).", name), Sugar::Match(name) => format!("You must implement '{}.match' in order to use the match notation (or derive match with #derive[match]).", name),
Sugar::Open(name) => format!("You must implement '{}.open' in order to use the open notation (or derive open with #derive[open]).", name), Sugar::Open(name) => format!("You must implement '{}.open' in order to use the open notation (or derive open with #derive[open]).", name),
}], }],

View File

@ -335,8 +335,10 @@ impl Visitor for UnboundCollector {
match &mut pat.data { match &mut pat.data {
PatKind::Var(ident) => self.visit_pat_ident(ident), PatKind::Var(ident) => self.visit_pat_ident(ident),
PatKind::Str(_) => (), PatKind::Str(_) => (),
PatKind::U60(_) => (),
PatKind::U120(_) => (),
PatKind::F60(_) => (),
PatKind::Char(_) => (), PatKind::Char(_) => (),
PatKind::Num(_) => (),
PatKind::Hole => (), PatKind::Hole => (),
PatKind::List(ls) => { PatKind::List(ls) => {
for pat in ls { for pat in ls {

View File

@ -33,7 +33,6 @@ pub fn compile_str(val: &str) -> Box<Term> {
} }
pub fn compile_term(expr: &untyped::Expr) -> Box<Term> { pub fn compile_term(expr: &untyped::Expr) -> Box<Term> {
use kind_tree::Number;
use untyped::ExprKind::*; use untyped::ExprKind::*;
match &expr.data { match &expr.data {
Var { name } => Box::new(Term::Var { Var { name } => Box::new(Term::Var {
@ -58,25 +57,10 @@ pub fn compile_term(expr: &untyped::Expr) -> Box<Term> {
expr: compile_term(val), expr: compile_term(val),
body: compile_term(next), body: compile_term(next),
}), }),
Num { U60 { numb } => Box::new(Term::U6O {
num: Number::U60(numb),
} => Box::new(Term::U6O {
numb: u60::new(*numb), numb: u60::new(*numb),
}), }),
Num { F60 { numb: _ } => todo!(),
num: Number::U120(numb),
} => {
let hi = Box::new(Term::U6O {
numb: u60::new((numb >> 60) as u64),
});
let lo = Box::new(Term::U6O {
numb: u60::new((numb & 0xFFFFFFFFFFFFFFF) as u64),
});
Box::new(Term::Ctr {
name: String::from("U120.new"),
args: vec![hi, lo],
})
}
Binary { op, left, right } => Box::new(Term::Ctr { Binary { op, left, right } => Box::new(Term::Ctr {
name: op.to_string(), name: op.to_string(),
args: vec![compile_term(left), compile_term(right)], args: vec![compile_term(left), compile_term(right)],

View File

@ -2,7 +2,7 @@ use std::{fmt::Display, sync::mpsc::Sender};
use fxhash::FxHashMap; use fxhash::FxHashMap;
use kind_report::data::Diagnostic; use kind_report::data::Diagnostic;
use kind_tree::{symbol::QualifiedIdent, untyped, Number}; use kind_tree::{symbol::QualifiedIdent, untyped};
use linked_hash_map::LinkedHashMap; use linked_hash_map::LinkedHashMap;
use tiny_keccak::Hasher; use tiny_keccak::Hasher;
@ -126,26 +126,26 @@ pub fn compile_book(
Ok(ctx.file) Ok(ctx.file)
} }
pub fn compile_rule(ctx: &mut CompileCtx, rule: &untyped::Rule) -> kindelia_lang::ast::Rule { pub fn compile_rule(ctx: &mut CompileCtx, rule: &untyped::Rule) -> kdl::Rule {
let name = *ctx.kdl_names.get(rule.name.to_str()).unwrap(); let name = *ctx.kdl_names.get(rule.name.to_str()).unwrap();
let mut args = Vec::new(); let mut args = Vec::new();
for pat in &rule.pats { for pat in &rule.pats {
let arg = compile_expr(ctx, pat); let arg = compile_expr(ctx, pat);
args.push(arg); args.push(arg);
} }
let lhs = kdl::Term::ctr(name, args); let lhs = kdl::Term::fun(name, args);
let rhs = compile_expr(ctx, &rule.body); let rhs = compile_expr(ctx, &rule.body);
kdl::Rule { lhs, rhs } kdl::Rule { lhs, rhs }
} }
pub fn err_term() -> kindelia_lang::ast::Term { pub fn err_term() -> kdl::Term {
kindelia_lang::ast::Term::Num { kdl::Term::Num {
numb: kindelia_lang::ast::U120::new(99999).unwrap(), numb: kdl::U120::new(99999).unwrap(),
} }
} }
pub fn compile_expr(ctx: &mut CompileCtx, expr: &untyped::Expr) -> kindelia_lang::ast::Term { pub fn compile_expr(ctx: &mut CompileCtx, expr: &untyped::Expr) -> kdl::Term {
use crate::untyped::ExprKind as From; use crate::untyped::ExprKind as From;
use kdl::Term as To; use kdl::Term as To;
match &expr.data { match &expr.data {
@ -202,10 +202,24 @@ pub fn compile_expr(ctx: &mut CompileCtx, expr: &untyped::Expr) -> kindelia_lang
} }
} }
From::Ctr { name, args } => { From::Ctr { name, args } => {
// Convert U120 numbers into the native kindelia representation
// Only possible if both U60s are U60 terms
if name.to_str() == "U120.new" {
if let (From::U60 { numb: hi }, From::U60 { numb: lo }) =
(&args[0].data, &args[1].data)
{
let numb = kdl::U120(((*hi as u128) << 60) | (*lo as u128));
return To::Num { numb };
}
}
let name = ctx.kdl_names.get(name.to_str()).unwrap().clone();
let args = args.iter().map(|x| compile_expr(ctx, &x)).collect();
To::Ctr { name, args }
}
From::Fun { name, args } => {
match name.to_str() { match name.to_str() {
// Special compilation for some numeric functions // Special inline compilation for
// They have no rules because they're compilation defined, // some numeric function applications
// so they've been initially interpreted as Ctr
// Add with no boundary check is just a normal add // Add with no boundary check is just a normal add
"U60.add_unsafe" => To::Op2 { "U60.add_unsafe" => To::Op2 {
@ -303,20 +317,13 @@ pub fn compile_expr(ctx: &mut CompileCtx, expr: &untyped::Expr) -> kindelia_lang
val0: Box::new(compile_expr(ctx, &args[0])), val0: Box::new(compile_expr(ctx, &args[0])),
val1: Box::new(compile_expr(ctx, &args[1])), val1: Box::new(compile_expr(ctx, &args[1])),
}, },
// All other constructors have a normal compilation
_ => { _ => {
let name = *ctx.kdl_names.get(name.to_str()).unwrap(); let name = ctx.kdl_names.get(name.to_str()).unwrap().clone();
let args = args.iter().map(|x| compile_expr(ctx, x)).collect(); let args = args.iter().map(|x| compile_expr(ctx, x)).collect();
To::Ctr { name, args } To::Fun { name, args }
} }
} }
} }
From::Fun { name, args } => {
let name = *ctx.kdl_names.get(name.to_str()).unwrap();
let args = args.iter().map(|x| compile_expr(ctx, x)).collect();
To::Fun { name, args }
}
From::Lambda { From::Lambda {
param, param,
body, body,
@ -334,25 +341,22 @@ pub fn compile_expr(ctx: &mut CompileCtx, expr: &untyped::Expr) -> kindelia_lang
From::Let { name, val, next } => { From::Let { name, val, next } => {
let res_name = kdl::Name::from_str(name.to_str()); let res_name = kdl::Name::from_str(name.to_str());
if let Ok(name) = res_name { if let Ok(name) = res_name {
let expr = Box::new(compile_expr(ctx, val)); let expr = Box::new(compile_expr(ctx, next));
let func = Box::new(To::Lam { name, body: expr }); let func = Box::new(To::Lam { name, body: expr });
let argm = Box::new(compile_expr(ctx, next)); let argm = Box::new(compile_expr(ctx, &val));
To::App { func, argm } To::App { func, argm }
} else { } else {
ctx.send_err(Box::new(KdlError::InvalidVarName(name.range))); ctx.send_err(Box::new(KdlError::InvalidVarName(name.range)));
err_term() err_term()
} }
} }
From::Num { From::U60 { numb } => To::Num {
num: Number::U60(numb),
} => To::Num {
numb: kdl::U120(*numb as u128), numb: kdl::U120(*numb as u128),
}, },
From::Num { From::F60 { numb: _ } => {
num: Number::U120(numb), ctx.send_err(Box::new(KdlError::FloatUsed(expr.range)));
} => To::Num { err_term()
numb: kdl::U120(*numb), }
},
From::Var { name } => { From::Var { name } => {
let res_name = kdl::Name::from_str(name.to_str()); let res_name = kdl::Name::from_str(name.to_str());
if let Ok(name) = res_name { if let Ok(name) = res_name {
@ -402,68 +406,114 @@ pub fn compile_entry(ctx: &mut CompileCtx, entry: &untyped::Entry) {
ctx.file.runs.push(statement); ctx.file.runs.push(statement);
} }
} else { } else {
let name = ctx.kdl_names.get(entry.name.to_str()).cloned().unwrap(); match entry.name.to_str() {
"U120.new" => compile_u120_new(ctx, entry),
let mut args = Vec::new(); _ => compile_common_function(ctx, entry),
for (name, range, _strictness) in &entry.args {
if let Ok(name) = kdl::Name::from_str(name) {
args.push(name)
} else {
ctx.send_err(Box::new(KdlError::InvalidVarName(*range)));
}
}
if entry.rules.is_empty() {
// Functions with no rules become Ctr
let sttm = kdl::Statement::Ctr {
name,
args,
sign: None,
};
ctx.file.ctrs.insert(entry.name.to_string(), sttm);
} else {
// Functions with rules become Fun
let rules = entry
.rules
.iter()
.map(|rule| compile_rule(ctx, rule))
.collect::<Vec<_>>();
let func = kdl::Func { rules };
let init = if let Some(state_name) = &entry.attrs.kdl_state {
let init_entry = ctx.book.entrs.get(state_name.to_str());
if let Some(entry) = init_entry {
if !entry.args.is_empty() {
ctx.send_err(Box::new(KdlError::ShouldNotHaveArguments(entry.range)));
None
} else if entry.rules.len() != 1 {
ctx.send_err(Box::new(KdlError::ShouldHaveOnlyOneRule(entry.range)));
None
} else {
ctx.kdl_states.push(state_name.to_string());
Some(compile_expr(ctx, &entry.rules[0].body))
}
} else {
ctx.send_err(Box::new(KdlError::NoInitEntry(state_name.range)));
None
}
} else {
None
};
let sttm = kdl::Statement::Fun {
name,
args,
func,
init,
sign: None,
};
ctx.file.funs.insert(entry.name.to_string(), sttm);
} }
} }
} }
fn compile_common_function(ctx: &mut CompileCtx, entry: &untyped::Entry) {
let name = ctx.kdl_names.get(entry.name.to_str()).cloned().unwrap();
let mut args = Vec::new();
for (name, range, _strictness) in &entry.args {
if let Ok(name) = kdl::Name::from_str(name) {
args.push(name)
} else {
ctx.send_err(Box::new(KdlError::InvalidVarName(*range)));
}
}
if entry.rules.is_empty() {
// Functions with no rules become Ctr
let sttm = kdl::Statement::Ctr {
name,
args,
sign: None,
};
ctx.file.ctrs.insert(entry.name.to_string(), sttm);
} else {
// Functions with rules become Fun
let rules = entry
.rules
.iter()
.map(|rule| compile_rule(ctx, rule))
.collect::<Vec<_>>();
let func = kdl::Func { rules };
let init = if let Some(state_name) = &entry.attrs.kdl_state {
let init_entry = ctx.book.entrs.get(state_name.to_str());
if let Some(entry) = init_entry {
if !entry.args.is_empty() {
ctx.send_err(Box::new(KdlError::ShouldNotHaveArguments(entry.range)));
None
} else if entry.rules.len() != 1 {
ctx.send_err(Box::new(KdlError::ShouldHaveOnlyOneRule(entry.range)));
None
} else {
ctx.kdl_states.push(state_name.to_string());
Some(compile_expr(ctx, &entry.rules[0].body))
}
} else {
ctx.send_err(Box::new(KdlError::NoInitEntry(state_name.range)));
None
}
} else {
None
};
let sttm = kdl::Statement::Fun {
name,
args,
func,
init,
sign: None,
};
ctx.file.funs.insert(entry.name.to_string(), sttm);
}
}
fn compile_u120_new(ctx: &mut CompileCtx, entry: &untyped::Entry) {
// U120.new hi lo = (hi << 60) | lo
let hi_name = kdl::Name::from_str("hi").unwrap();
let lo_name = kdl::Name::from_str("lo").unwrap();
let hi_var = kdl::Term::Var {
name: hi_name.clone(),
};
let lo_var = kdl::Term::Var {
name: lo_name.clone(),
};
let name = ctx.kdl_names.get(entry.name.to_str()).cloned().unwrap();
let args = vec![hi_name, lo_name];
let rules = vec![kdl::Rule {
lhs: kdl::Term::Fun {
name: name.clone(),
args: vec![hi_var.clone(), lo_var.clone()],
},
rhs: kdl::Term::Op2 {
oper: kdl::Oper::Or,
val0: Box::new(kdl::Term::Op2 {
oper: kdl::Oper::Shl,
val0: Box::new(hi_var),
val1: Box::new(kdl::Term::Num {
numb: kdl::U120(60),
}),
}),
val1: Box::new(lo_var),
},
}];
let func = kdl::Func { rules };
let sttm = kdl::Statement::Fun {
name,
args,
func,
init: None,
sign: None,
};
ctx.file.funs.insert(entry.name.to_string(), sttm);
}
impl Display for File { impl Display for File {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for ctr in &self.ctrs { for ctr in &self.ctrs {

View File

@ -6,6 +6,7 @@ pub enum KdlError {
ShouldNotHaveArguments(Range), ShouldNotHaveArguments(Range),
ShouldHaveOnlyOneRule(Range), ShouldHaveOnlyOneRule(Range),
NoInitEntry(Range), NoInitEntry(Range),
FloatUsed(Range),
} }
impl Diagnostic for KdlError { impl Diagnostic for KdlError {
@ -15,6 +16,7 @@ impl Diagnostic for KdlError {
KdlError::ShouldNotHaveArguments(range) => Some(range.ctx), KdlError::ShouldNotHaveArguments(range) => Some(range.ctx),
KdlError::ShouldHaveOnlyOneRule(range) => Some(range.ctx), KdlError::ShouldHaveOnlyOneRule(range) => Some(range.ctx),
KdlError::NoInitEntry(range) => Some(range.ctx), KdlError::NoInitEntry(range) => Some(range.ctx),
KdlError::FloatUsed(range) => Some(range.ctx),
} }
} }
@ -65,7 +67,21 @@ impl Diagnostic for KdlError {
KdlError::NoInitEntry(range) => DiagnosticFrame { KdlError::NoInitEntry(range) => DiagnosticFrame {
code: 604, code: 604,
severity: Severity::Error, severity: Severity::Error,
title: "This entry have to have a init entry".to_string(), title: "This entry must have a init entry".to_string(),
subtitles: vec![],
hints: vec![],
positions: vec![Marker {
position: *range,
color: Color::Fst,
text: "Here!".to_string(),
no_code: false,
main: true,
}],
},
KdlError::FloatUsed(range) => DiagnosticFrame {
code: 605,
severity: Severity::Error,
title: "Found F60 in kindelia program".to_string(),
subtitles: vec![], subtitles: vec![],
hints: vec![], hints: vec![],
positions: vec![Marker { positions: vec![Marker {

View File

@ -10,7 +10,10 @@ fn must_split(rule: &Rule) -> bool {
for pat in &rule.pats { for pat in &rule.pats {
if let ExprKind::Ctr { args, .. } = &pat.data { if let ExprKind::Ctr { args, .. } = &pat.data {
for arg in args { for arg in args {
if matches!(arg.data, ExprKind::Ctr { .. } | ExprKind::Num { .. }) { if matches!(
arg.data,
ExprKind::Ctr { .. } | ExprKind::U60 { .. } | ExprKind::F60 { .. }
) {
return true; return true;
} }
} }
@ -27,19 +30,41 @@ fn matches_together(a: &Rule, b: &Rule) -> (bool, bool) {
(ExprKind::Ctr { name: an, .. }, ExprKind::Ctr { name: bn, .. }) if an != bn => { (ExprKind::Ctr { name: an, .. }, ExprKind::Ctr { name: bn, .. }) if an != bn => {
return (false, false); return (false, false);
} }
(ExprKind::Num { num: a_numb }, ExprKind::Num { num: b_numb }) if a_numb != b_numb => { (ExprKind::U60 { numb: a_numb }, ExprKind::U60 { numb: b_numb })
if a_numb != b_numb =>
{
return (false, false); return (false, false);
} }
(ExprKind::Ctr { .. }, ExprKind::Num { .. }) => { (ExprKind::F60 { numb: a_numb }, ExprKind::F60 { numb: b_numb })
if a_numb != b_numb =>
{
return (false, false); return (false, false);
} }
(ExprKind::Num { .. }, ExprKind::Ctr { .. }) => { (ExprKind::Ctr { .. }, ExprKind::U60 { .. }) => {
return (false, false);
}
(ExprKind::Ctr { .. }, ExprKind::F60 { .. }) => {
return (false, false);
}
(ExprKind::U60 { .. }, ExprKind::Ctr { .. }) => {
return (false, false);
}
(ExprKind::U60 { .. }, ExprKind::F60 { .. }) => {
return (false, false);
}
(ExprKind::F60 { .. }, ExprKind::U60 { .. }) => {
return (false, false);
}
(ExprKind::F60 { .. }, ExprKind::Ctr { .. }) => {
return (false, false); return (false, false);
} }
(ExprKind::Ctr { .. }, ExprKind::Var { .. }) => { (ExprKind::Ctr { .. }, ExprKind::Var { .. }) => {
same_shape = false; same_shape = false;
} }
(ExprKind::Num { .. }, ExprKind::Var { .. }) => { (ExprKind::U60 { .. }, ExprKind::Var { .. }) => {
same_shape = false;
}
(ExprKind::F60 { .. }, ExprKind::Var { .. }) => {
same_shape = false; same_shape = false;
} }
_ => {} _ => {}
@ -80,7 +105,7 @@ fn split_rule(
old_rule_pats.push(pat.clone()); old_rule_pats.push(pat.clone());
old_rule_body_args.push(Expr::var(name.clone())); old_rule_body_args.push(Expr::var(name.clone()));
} }
ExprKind::Num { .. } => { ExprKind::U60 { .. } | ExprKind::F60 { .. } => {
old_rule_pats.push(pat.clone()); old_rule_pats.push(pat.clone());
} }
ExprKind::Ctr { name, args } => { ExprKind::Ctr { name, args } => {
@ -88,7 +113,7 @@ fn split_rule(
for field in args { for field in args {
let arg = match &field.data { let arg = match &field.data {
ExprKind::Ctr { .. } | ExprKind::Num { .. } => { ExprKind::Ctr { .. } | ExprKind::U60 { .. } | ExprKind::F60 { .. } => {
let name = Ident::new(format!(".x{}", var_count), field.range); let name = Ident::new(format!(".x{}", var_count), field.range);
var_count += 1; var_count += 1;
Expr::var(name) Expr::var(name)
@ -150,9 +175,13 @@ fn split_rule(
(ExprKind::Var { .. }, _) => { (ExprKind::Var { .. }, _) => {
new_rule_pats.push(other_pat.clone()); new_rule_pats.push(other_pat.clone());
} }
(ExprKind::Num { .. }, ExprKind::Num { .. }) => (), (ExprKind::U60 { .. }, ExprKind::U60 { .. }) => (),
(ExprKind::Num { .. }, ExprKind::Var { name }) => { (ExprKind::F60 { .. }, ExprKind::F60 { .. }) => (),
subst(&mut new_rule_body, name, rule_pat); (ExprKind::U60 { .. }, ExprKind::Var { name }) => {
subst(&mut new_rule_body, &name, rule_pat);
}
(ExprKind::F60 { .. }, ExprKind::Var { name }) => {
subst(&mut new_rule_body, &name, rule_pat);
} }
_ => { _ => {
panic!("Internal error. Please report."); // not possible since it matches panic!("Internal error. Please report."); // not possible since it matches

View File

@ -34,8 +34,6 @@ pub fn compile_book(
let file = compile::compile_book(&flattened, sender, namespace)?; let file = compile::compile_book(&flattened, sender, namespace)?;
println!("{}", file);
let file = linearize::linearize_file(file); let file = linearize::linearize_file(file);
Ok(file) Ok(file)
} }

View File

@ -41,7 +41,7 @@ impl LinearizeCtx {
// for every variable found in the style described before with // for every variable found in the style described before with
// the fresh function. Also checks if rule's left side is valid. // the fresh function. Also checks if rule's left side is valid.
fn create_param_names(&mut self, rule: &Rule) { fn create_param_names(&mut self, rule: &Rule) {
if let Term::Ctr { name: _, args } = &rule.lhs { if let Term::Fun { name: _, args } = &rule.lhs {
for arg in args { for arg in args {
match arg { match arg {
Term::Var { name } => { Term::Var { name } => {
@ -237,7 +237,9 @@ pub fn linearize_term(ctx: &mut LinearizeCtx, term: &Term, lhs: bool) -> Box<Ter
args: new_args, args: new_args,
} }
} }
Term::Num { numb } => Term::Num { numb: *numb }, Term::Num { numb } => {
Term::Num { numb: *numb }
}
Term::Op2 { oper, val0, val1 } => { Term::Op2 { oper, val0, val1 } => {
let val0 = linearize_term(ctx, val0, lhs); let val0 = linearize_term(ctx, val0, lhs);
let val1 = linearize_term(ctx, val1, lhs); let val1 = linearize_term(ctx, val1, lhs);
@ -273,8 +275,8 @@ pub fn dup_var(ctx: &mut LinearizeCtx, name: &Name, expr: Box<Term>, body: Box<T
// if used once just make a let (lambda then app) // if used once just make a let (lambda then app)
1 => { 1 => {
let name = Name::from_str(&format!("{}.0", name)).unwrap(); // TODO: handle err let name = Name::from_str(&format!("{}.0", name)).unwrap(); // TODO: handle err
let func = Box::new(Term::Lam { name, body: expr }); let func = Box::new(Term::Lam { name, body });
let term = Term::App { func, argm: body }; let term = Term::App { func, argm: expr };
Box::new(term) Box::new(term)
} }
// if used more than once, duplicate // if used more than once, duplicate

View File

@ -32,11 +32,12 @@ pub fn subst(term: &mut Expr, from: &Ident, to: &Expr) {
Lambda { param, body, .. } if param.to_str() != from.to_str() => subst(body, from, to), Lambda { param, body, .. } if param.to_str() != from.to_str() => subst(body, from, to),
Num { .. } => (), U60 { .. } => (),
F60 { .. } => (),
Str { .. } => (), Str { .. } => (),
Var { .. } => (), Var { .. } => (),
Lambda { .. } => (), Lambda { .. } => (),
Err => unreachable!("Err should not be used inside the compiledr"), Err => unreachable!("Err should not be used inside the compiler"),
} }
} }

View File

@ -1,7 +1,7 @@
ERROR Type mismatch ERROR Type mismatch
* Got : (Eq _ 123u120 123u120) * Got : (Eq _ (U120.new 0 123) (U120.new 0 123))
* Expected : (Eq _ 123u120 124u120) * Expected : (Eq _ (U120.new 0 123) (U120.new 0 124))
/--[suite/checker/derive/fail/WrongU120Eq.kind2:12:9] /--[suite/checker/derive/fail/WrongU120Eq.kind2:12:9]

View File

@ -0,0 +1,4 @@
fun (JOJO ) {
(JOJO) = #42
}

View File

@ -1,3 +1,4 @@
#kdl_name = JOJO #kdl_name = JOJO
#keep
Jonathan.Joestar : U60 Jonathan.Joestar : U60
Jonathan.Joestar = 42 Jonathan.Joestar = 42

View File

@ -0,0 +1,8 @@
fun (CoolFnApp n) {
(CoolFnApp x0) = (!@x0.0 (!@x1 (!@x1.0 (!x1.0 x0.0) x1) @x2 (!@x2.0 (!(CoolFn) x2.0) x2)) x0)
}
fun (CoolFn ) {
(CoolFn) = @x0 (!@x0.0 (& (* #2 x0.0) #1152921504606846975) x0)
}

View File

@ -1,7 +1,9 @@
#keep
CoolFn : U60 -> U60 { CoolFn : U60 -> U60 {
(x: U60) => (* 2 x) (x: U60) => (* 2 x)
} }
#keep
CoolFnApp (n: U60) : U60 { CoolFnApp (n: U60) : U60 {
let lam = (x: U60) => ((CoolFn) x) let lam = (x: U60) => ((CoolFn) x)
(lam n) (lam n)

View File

@ -0,0 +1,10 @@
ctr {List.cons h t}
fun (U120.new hi lo) {
(U120.new x0 x1) = (!@x1.0 (!@x0.0 (| (<< x0.0 #60) x1.0) x0) x1)
}
fun (TestFunc xs) {
(TestFunc {List.cons ~ x1}) = (!@x1.0 (!@x2 dup c.0 x2.0 = x2; dup x2.1 x2.2 = c.0; (!@x3 (!@x3.0 (!@~ {List.cons {U120.add x2.0 x3.0} x1.0} #4) x3) {U120.add x2.1 x2.2}) #2) x1)
}

View File

@ -0,0 +1,17 @@
U120 : Type
U120.new (a: U60) (b: U60) : U120
#kdl_erase
U120.add (a: U120) (b: U120) : U120
List : Type
List.nil : List
List.cons (h: U120) (t: List) : Type
#keep
TestFunc (xs: List) : List
TestFunc (List.cons h t) =
let aa = 2u120
let bb = (U120.add aa aa)
let cc = 4u120
List.cons (U120.add aa bb) t

View File

@ -1 +1,10 @@
ctr {MyFn.state} ERROR This entry should only have one rule.
/--[suite/kdl/NonInlineState.kind2:7:1]
|
6 |
7 | MyFn.state : U60
| v---------------
| \Here!

View File

@ -1,4 +1,5 @@
#kdl_state = MyFn.state #kdl_state = MyFn.state
#keep
MyFn : U60 { MyFn : U60 {
1 1
} }

View File

@ -1,5 +1,5 @@
fun (A ) { fun (A ) {
{A} = #2 (A) = #2
} }
run { run {

View File

@ -0,0 +1,4 @@
fun (NDFMHGgkiOr2 ) {
(NDFMHGgkiOr2) = #0
}

View File

@ -1,3 +1,4 @@
#keep
FunctionWithAVeryLongName : U60 { FunctionWithAVeryLongName : U60 {
0 0
} }

View File

@ -1,4 +1,4 @@
fun (A ) { fun (A ) {
{A} = (& (+ (B) #1) #1152921504606846975) (A) = (& (+ (B) #1) #1152921504606846975)
} }

View File

@ -1,3 +1,3 @@
run { run {
#2 #2
} }

View File

@ -1,4 +1,3 @@
#kdl_run #kdl_run
#keep
Main: U60 Main: U60
Main = 2 Main = 2

View File

@ -83,12 +83,17 @@ pub enum Literal {
/// The help operator that prints the context /// The help operator that prints the context
/// and the goal (e.g. ?) /// and the goal (e.g. ?)
Help(Ident), Help(Ident),
/// The type of 60 bits numberss (e.g. 2 : U60) /// The type literal of 60 bit numbers (e.g. 2 : U60)
NumType(crate::NumType), NumTypeU60,
NumTypeF60,
// Char literal // Char literal
Char(char), Char(char),
/// A number literal of 60 bits (e.g 32132) /// A 60 bit number literal (e.g 32132)
Number(crate::Number), NumU60(u64),
// A 120 bit number literal
NumU120(u128),
// A 60 bit floating point number literal
NumF60(u64),
// A String literal // A String literal
String(String), String(String),
} }
@ -309,11 +314,12 @@ impl Display for Literal {
match self { match self {
Literal::Help(s) => write!(f, "?{}", s), Literal::Help(s) => write!(f, "?{}", s),
Literal::Type => write!(f, "Type"), Literal::Type => write!(f, "Type"),
Literal::NumType(crate::NumType::U60) => write!(f, "U60"), Literal::NumTypeU60 => write!(f, "U60"),
Literal::NumType(crate::NumType::U120) => write!(f, "U120"), Literal::NumTypeF60 => write!(f, "F60"),
Literal::Char(c) => write!(f, "'{}'", c), Literal::Char(c) => write!(f, "'{}'", c),
Literal::Number(crate::Number::U60(numb)) => write!(f, "{}", numb), Literal::NumU60(numb) => write!(f, "{}", numb),
Literal::Number(crate::Number::U120(numb)) => write!(f, "{}u120", numb), Literal::NumF60(_numb) => todo!(),
Literal::NumU120(numb) => write!(f, "{}u120", numb),
Literal::String(str) => { Literal::String(str) => {
write!(f, "{:?}", str) write!(f, "{:?}", str)
} }

View File

@ -19,8 +19,12 @@ pub enum PatKind {
Var(PatIdent), Var(PatIdent),
/// Application of a constructor /// Application of a constructor
App(QualifiedIdent, Vec<Box<Pat>>), App(QualifiedIdent, Vec<Box<Pat>>),
/// Number /// 60 bit unsigned integer
Num(crate::Number), U60(u64),
/// 120 bit unsigned integer
U120(u128),
/// 60 bit floating point number
F60(u64),
/// Pair /// Pair
Pair(Box<Pat>, Box<Pat>), Pair(Box<Pat>, Box<Pat>),
/// List /// List
@ -60,9 +64,10 @@ impl Display for Pat {
.join(" ") .join(" ")
), ),
Str(str) => write!(f, "\"{}\"", str), Str(str) => write!(f, "\"{}\"", str),
U60(num) => write!(f, "{}", num),
U120(num) => write!(f, "{}u120", num),
F60(_num) => todo!(),
Char(chr) => write!(f, "\'{}\'", chr), Char(chr) => write!(f, "\'{}\'", chr),
Num(crate::Number::U60(num)) => write!(f, "{}", num),
Num(crate::Number::U120(num)) => write!(f, "{}u120", num),
Pair(fst, snd) => write!(f, "({}, {})", fst, snd), Pair(fst, snd) => write!(f, "({}, {})", fst, snd),
Hole => write!(f, "_"), Hole => write!(f, "_"),
} }

View File

@ -280,8 +280,10 @@ pub fn walk_pat<T: Visitor>(ctx: &mut T, pat: &mut Pat) {
match &mut pat.data { match &mut pat.data {
PatKind::Var(ident) => ctx.visit_pat_ident(ident), PatKind::Var(ident) => ctx.visit_pat_ident(ident),
PatKind::Str(_) => (), PatKind::Str(_) => (),
PatKind::U60(_) => (),
PatKind::U120(_) => (),
PatKind::F60(_) => (),
PatKind::Char(_) => (), PatKind::Char(_) => (),
PatKind::Num(_) => (),
PatKind::Hole => (), PatKind::Hole => (),
PatKind::List(ls) => { PatKind::List(ls) => {
for pat in ls { for pat in ls {

View File

@ -7,11 +7,11 @@ use fxhash::FxHashMap;
use kind_span::Range; use kind_span::Range;
use linked_hash_map::LinkedHashMap; use linked_hash_map::LinkedHashMap;
pub use crate::Operator;
use crate::{ use crate::{
symbol::{Ident, QualifiedIdent}, symbol::{Ident, QualifiedIdent},
Attributes, Attributes,
}; };
pub use crate::{NumType, Number, Operator};
/// Just a vector of expressions. It is called spine because /// Just a vector of expressions. It is called spine because
/// it is usually in a form like (a b c d e) that can be interpret /// it is usually in a form like (a b c d e) that can be interpret
@ -67,10 +67,14 @@ pub enum ExprKind {
}, },
/// Type Literal /// Type Literal
Typ, Typ,
/// Primitive numeric types /// 60 bit integer type
NumType { typ: crate::NumType }, NumTypeU60,
/// Primitive numeric values /// 60 bit floating point number type
Num { num: crate::Number }, NumTypeF60,
/// 60 bit integer
NumU60 { numb: u64 },
/// 60 bit floating point number
NumF60 { numb: u64 },
/// Very special constructor :) /// Very special constructor :)
Str { val: String }, Str { val: String },
/// Binary operation (e.g. 2 + 3) /// Binary operation (e.g. 2 + 3)
@ -207,39 +211,44 @@ impl Expr {
}) })
} }
pub fn u60(range: Range) -> Box<Expr> { pub fn type_u60(range: Range) -> Box<Expr> {
Box::new(Expr { Box::new(Expr {
range, range,
data: ExprKind::NumType { data: ExprKind::NumTypeU60,
typ: crate::NumType::U60, })
}
pub fn type_f60(range: Range) -> Box<Expr> {
Box::new(Expr {
range,
data: ExprKind::NumTypeF60,
})
}
pub fn num_u60(range: Range, numb: u64) -> Box<Expr> {
Box::new(Expr {
range,
data: ExprKind::NumU60 { numb },
})
}
pub fn num_u120(range: Range, numb: u128) -> Box<Expr> {
let name = QualifiedIdent::new_static("U120.new", None, range);
let lo = Expr::num_u60(range, (numb & 0xFFFFFFFFFFFFFFF) as u64);
let hi = Expr::num_u60(range, (numb >> 60) as u64);
Box::new(Expr {
range,
data: ExprKind::Ctr {
name,
args: vec![hi, lo],
}, },
}) })
} }
pub fn u120(range: Range) -> Box<Expr> { pub fn num_f60(range: Range, numb: u64) -> Box<Expr> {
Box::new(Expr { Box::new(Expr {
range, range,
data: ExprKind::NumType { data: ExprKind::NumF60 { numb },
typ: crate::NumType::U120,
},
})
}
pub fn num60(range: Range, num: u64) -> Box<Expr> {
Box::new(Expr {
range,
data: ExprKind::Num {
num: crate::Number::U60(num),
},
})
}
pub fn num120(range: Range, num: u128) -> Box<Expr> {
Box::new(Expr {
range,
data: ExprKind::Num {
num: crate::Number::U120(num),
},
}) })
} }
@ -371,19 +380,11 @@ impl Display for Expr {
use ExprKind::*; use ExprKind::*;
match &self.data { match &self.data {
Typ => write!(f, "Type"), Typ => write!(f, "Type"),
NumType { NumTypeU60 => write!(f, "U60"),
typ: crate::NumType::U60, NumTypeF60 => write!(f, "F60"),
} => write!(f, "U60"),
NumType {
typ: crate::NumType::U120,
} => write!(f, "U120"),
Str { val } => write!(f, "\"{}\"", val), Str { val } => write!(f, "\"{}\"", val),
Num { NumU60 { numb } => write!(f, "{}", numb),
num: crate::Number::U60(n), NumF60 { numb: _ } => todo!(),
} => write!(f, "{}", n),
Num {
num: crate::Number::U120(n),
} => write!(f, "{}u120", n),
All { .. } => write!(f, "({})", self.traverse_pi_types()), All { .. } => write!(f, "({})", self.traverse_pi_types()),
Var { name } => write!(f, "{}", name), Var { name } => write!(f, "{}", name),
Lambda { Lambda {

View File

@ -55,16 +55,3 @@ pub enum Operator {
Gtn, Gtn,
Neq, Neq,
} }
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum Number {
U60(u64),
U120(u128),
// TODO: F60
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum NumType {
U60,
U120,
}

View File

@ -7,11 +7,11 @@ use fxhash::FxHashMap;
use kind_span::Range; use kind_span::Range;
use linked_hash_map::LinkedHashMap; use linked_hash_map::LinkedHashMap;
pub use crate::Operator;
use crate::{ use crate::{
symbol::{Ident, QualifiedIdent}, symbol::{Ident, QualifiedIdent},
Attributes, Attributes,
}; };
pub use crate::{NumType, Number, Operator};
/// Just a vector of expressions. It is called spine because /// Just a vector of expressions. It is called spine because
/// it is usually in a form like (a b c d e) that can be interpret /// it is usually in a form like (a b c d e) that can be interpret
@ -51,9 +51,13 @@ pub enum ExprKind {
val: Box<Expr>, val: Box<Expr>,
next: Box<Expr>, next: Box<Expr>,
}, },
/// Primitive numeric values /// 60 bit unsigned integer
Num { U60 {
num: crate::Number, numb: u64,
},
/// 60 bit floating point number
F60 {
numb: u64,
}, },
/// Very special constructor :) /// Very special constructor :)
Str { Str {
@ -129,21 +133,17 @@ impl Expr {
}) })
} }
pub fn num60(range: Range, num: u64) -> Box<Expr> { pub fn u60(range: Range, numb: u64) -> Box<Expr> {
Box::new(Expr { Box::new(Expr {
range, range,
data: ExprKind::Num { data: ExprKind::U60 { numb },
num: crate::Number::U60(num),
},
}) })
} }
pub fn num120(range: Range, num: u128) -> Box<Expr> { pub fn f60(range: Range, numb: u64) -> Box<Expr> {
Box::new(Expr { Box::new(Expr {
range, range,
data: ExprKind::Num { data: ExprKind::F60 { numb },
num: crate::Number::U120(num),
},
}) })
} }
@ -223,12 +223,8 @@ impl Display for Expr {
match &self.data { match &self.data {
Err => write!(f, "ERR"), Err => write!(f, "ERR"),
Str { val } => write!(f, "\"{}\"", val), Str { val } => write!(f, "\"{}\"", val),
Num { U60 { numb } => write!(f, "{}", numb),
num: crate::Number::U60(n), F60 { numb: _ } => todo!(),
} => write!(f, "{}", n),
Num {
num: crate::Number::U120(n),
} => write!(f, "{}u120", n),
Var { name } => write!(f, "{}", name), Var { name } => write!(f, "{}", name),
Lambda { Lambda {
param, param,

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 483 KiB

BIN
perf.data

Binary file not shown.