Compare commits

...

3 commits

5 changed files with 284 additions and 123 deletions

View file

@ -6,4 +6,5 @@ edition = "2021"
[dependencies] [dependencies]
laddertypes = { path = "../lib-laddertypes" } laddertypes = { path = "../lib-laddertypes" }
tisc = { path = "../lib-tisc" } tisc = { path = "../lib-tisc" }
iterate-text = "0.0.1"

196
main.lt Normal file
View file

@ -0,0 +1,196 @@
{
/*
* Integer Operations
*/
let int-sign = λx:~machine.Int64 ↦ bit-and (bit-shr x 63) 1;
let int-neg = λx:~machine.Int64 ↦ i+ (bit-neg x) 1;
let int-abs = λx:~machine.Int64 ↦ if( int-sign x ) { int-neg x; } else { x; };
let int-lt = λ{ a:~machine.Int64; b:~machine.Int64; } ↦ int-sign (i- a b);
let int-gt = λ{ a:~machine.Int64; b:~machine.Int64; } ↦ int-sign (i- b a);
let int-eq = λ{ a:~machine.Int64; b:~machine.Int64; } ↦ if (i- a b) { 0; } else { 1; };
let int-lte = λ{ a:~machine.Int64; b:~machine.Int64; } ↦ bit-or (int-lt a b) (int-eq a b);
let int-gte = λ{ a:~machine.Int64; b:~machine.Int64; } ↦ bit-or (int-gt a b) (int-eq a b);
let int-min = λ{ a:~machine.Int64; b:~machine.Int64; } ↦ if( int-lt a b ) { a; } else { b; };
let int-max = λ{ a:~machine.Int64; b:~machine.Int64; } ↦ if( int-gt a b ) { a; } else { b; };
/* Euclidean Algorithm to calculate greatest common divisor
*/
let gcd = λ{
a : ~ machine.Int64;
b : ~ machine.Int64;
} ↦ {
while( b ) {
let tmp = i% a b;
! a b;
! b tmp;
}
a;
};
/* least common multiple
*/
let lcm = λ{
a : ~ machine.Int64;
b : ~ machine.Int64;
} ↦ i* (int-abs a) (i/ (int-abs b) (gcd a b));
/* Implementation of Rational Numbers
*/
let ratio-scale = λ{
{p:; q:;} : ~ <Ratio ~machine.UInt64> ;
n : ~ machine.UInt64 ;
} ↦ {
i* q n;
i* p n;
};
let ratio-normalize = λ{
p: ~machine.Int64;
q: ~machine.Int64;
} : ~ <Ratio ~machine.Int64>
↦ {
let s = gcd p q;
i/ q s;
i/ p s;
};
let ratio-add = λ{
{ap:; aq:;}: ~ <Ratio ~ _2^64 ~ machine.UInt64> ;
{bp:; bq:;}: ~ <Ratio ~ _2^64 ~ machine.UInt64> ;
} ↦ {
let l = lcm aq bq;
let as = i/ l aq;
let bs = i/ l bq;
i* aq as;
i+ (i* ap as) (i* bp bs);
};
let ratio-mul = λ{
{ap:; aq:;}: ~ <Ratio ~ _2^64 ~ machine.Int64> ;
{bp:; bq:;}: ~ <Ratio ~ _2^64 ~ machine.Int64> ;
} ↦ ratio-normalize (i* ap bp) (i* aq bq);
let morph-int-to-float =
λx: ~ machine.Int64 ~ machine.Word
↦ {
/* todo */
0;
};
let morph-ratio-to-float =
λ{
p : ~machine.Int64;
q : ~machine.Int64;
} : ~<Ratio ~machine.Int64>
↦ f/ (morph-int-to-float p) (morph-int-to-float q);
/* string output
*/
let print-nullterm =
λ{} : < Seq Char ~Ascii ~ machine.Word >
~ < NullTerminatedArray machine.Word >
↦ {
while(dup) { emit; }
drop;
};
print-nullterm 'H' 'a' 'l' 'l' 'o' ' ' 'W' 'e' 'l' 't' '!' '\n' '\0';
/* integer formatting
*/
let fmt-uint-radix = λ{
radix : ~ _2^64 ~ machine.UInt64;
x : ~ _2^64 ~ machine.UInt64;
} ↦ {
if( x ) {
while( x ) {
let digit = (i% x radix);
if( int-lt digit 10 ) {
i+ '0' digit;
} else {
i+ (i- 'a' 10) digit;
};
! x (i/ x radix);
}
} else {
'0';
};
};
let fmt-int-radix = λ{
radix: ~ _2^64 ~ machine.UInt64;
x : ~ machine.Int64;
} ↦ {
fmt-uint-radix radix (int-abs x);
if( int-sign x ) { '-'; };
};
let fmt-uint = λx: ↦ fmt-uint-radix 10 x;
let fmt-int = λx: ↦ fmt-int-radix 10 x;
/* ratio formatting
*/
let fmt-ratio = λ{ p:; q:; } : ~<Ratio ~machine.Int64> ↦ {
fmt-int q;':';fmt-int p;
};
/* test ratio
*/
print-nullterm
(fmt-ratio { 4; int-neg 3; })
' ''*'' '
(fmt-ratio { 7; 4; })
' ''='' '
(fmt-ratio (ratio-mul { 4; int-neg 3; } { 7; 4; }))
'\n''\0';
/* Vec3i
*/
let vec3i-add = λ{
{ ax:_2^64; ay:_2^64; az:_2^64; } : <Vec3 _2^64~machine.Int64>;
{ bx:_2^64; by:_2^64; bz:_2^64; } : <Vec3 _2^64~machine.Int64>;
} ↦ {
i+ az bz;
i+ ay by;
i+ ax bx;
};
let fmt-vec3i =
λ{ x:_2^64; y:_2^64; z:_2^64; } : <Vec3 _2^64~machine.Int64>
↦ {
'}';
fmt-int z; '='; 'z'; ' '; ';';
fmt-int y; '='; 'y'; ' '; ';';
fmt-int x; '='; 'x'; '{';
};
/* Colors
*/
let red-u8rgb
: <Fn <> Color ~ RGB ~ <Vec3 _0,1 ~ _256 ~ machine.UInt64>>
= λ{} ↦ { 0; 0; 255; };
let green-u8rgb = λ{} ↦ { 0; 255; 0; };
let blue-u8rgb = λ{} ↦ { 255; 0; 0; };
let yellow-u8rgb = λ{} ↦ { 0; 220; 220; };
print-nullterm
(fmt-vec3i green-u8rgb)
' ''+'' '
(fmt-vec3i blue-u8rgb)
' ''='' '
(fmt-vec3i (vec3i-add green-u8rgb blue-u8rgb))
'\n''\0';
}

View file

@ -1,5 +1,6 @@
#[derive(PartialEq, Eq, Clone, Debug)] #[derive(PartialEq, Eq, Clone, Debug)]
pub enum LTIRToken { pub enum LTIRToken {
Comment(String),
Symbol(String), Symbol(String),
Char(char), Char(char),
Num(i64), Num(i64),
@ -29,6 +30,7 @@ pub enum LexError {
#[derive(PartialEq, Eq, Clone, Debug)] #[derive(PartialEq, Eq, Clone, Debug)]
pub enum LexerState { pub enum LexerState {
Any, Any,
Comment(String),
TypeTerm(String), TypeTerm(String),
Sym(String), Sym(String),
Num(i64), Num(i64),
@ -39,6 +41,7 @@ impl LexerState {
fn into_token(self) -> Option<LTIRToken> { fn into_token(self) -> Option<LTIRToken> {
match self { match self {
LexerState::Any => None, LexerState::Any => None,
LexerState::Comment(s) => Some(LTIRToken::Comment(s)),
LexerState::TypeTerm(s) => Some(LTIRToken::AssignType(s)), LexerState::TypeTerm(s) => Some(LTIRToken::AssignType(s)),
LexerState::Sym(s) => Some(LTIRToken::Symbol(s)), LexerState::Sym(s) => Some(LTIRToken::Symbol(s)),
LexerState::Num(n) => Some(LTIRToken::Num(n)), LexerState::Num(n) => Some(LTIRToken::Num(n)),
@ -169,6 +172,22 @@ where
region.end += 1; region.end += 1;
state = LexerState::Char(None); state = LexerState::Char(None);
} }
'/' => {
self.chars.next();
self.position += 1;
region.end += 1;
match self.chars.next() {
Some('*') => {
self.position += 1;
region.end += 1;
state = LexerState::Comment(String::new());
}
_ => {
return Some((region, Err(LexError::InvalidChar)));
}
}
}
c => { c => {
if c.is_whitespace() { if c.is_whitespace() {
self.chars.next(); self.chars.next();
@ -183,6 +202,38 @@ where
} }
}, },
LexerState::Comment(s) => {
match self.chars.next() {
Some('*') => {
match self.chars.peek() {
Some('/') => {
self.chars.next();
self.position += 2;
region.end += 2;
if let Some(token) = state.clone().into_token() {
return Some((region, Ok(token)));
}
}
_ => {
s.push('*');
self.position += 1;
region.end += 1;
}
}
}
Some(c) => {
s.push(c);
self.position += 1;
region.end += 1;
}
None => {
return Some((region, Err(LexError::InvalidChar)));
}
}
}
LexerState::Char(val) => { LexerState::Char(val) => {
self.position += 2; self.position += 2;
region.end += 2; region.end += 2;
@ -288,6 +339,7 @@ mod tests {
fn test_lexer() { fn test_lexer() {
let mut lexer = crate::lexer::LTIRLexer::from( let mut lexer = crate::lexer::LTIRLexer::from(
"let var1:=123; "let var1:=123;
/* comment */
let square =λx.* x x; let square =λx.* x x;
let sqrt = λx:~machine::Float64~machine::Word.(f64-sqrt x); let sqrt = λx:~machine::Float64~machine::Word.(f64-sqrt x);

View file

@ -20,13 +20,18 @@ use crate::{
fn compile( fn compile(
scope: &Arc<RwLock<Scope>>, scope: &Arc<RwLock<Scope>>,
name: &str, name: &str,
source: &str, source: impl Iterator<Item = char>,
) -> Vec<tisc::assembler::AssemblyWord> { ) -> Vec<tisc::assembler::AssemblyWord> {
ProcedureCompiler::new(scope) ProcedureCompiler::new(scope)
.compile( .compile(
&parser::parse_expr( &parser::parse_expr(
&scope.read().unwrap().typectx, &scope.read().unwrap().typectx,
&mut lexer::LTIRLexer::from(source.chars().peekable()).peekable(), &mut lexer::LTIRLexer::from(source.peekable())
.filter(|tok| match tok {
(_, Ok(lexer::LTIRToken::Comment(_))) => false,
_ => true
})
.peekable(),
) )
.expect("syntax error"), .expect("syntax error"),
) )
@ -35,11 +40,10 @@ fn compile(
/* TODO: /* TODO:
* - Parse Comments
* - write to address resulting from expression
* - `::` -> '.' and allow only
* - Parser error reporting * - Parser error reporting
* - Compiler error reporting * - Compiler error reporting
* - write to address resulting from expression
* - sized objects
* - Typecheck for LTExpr::Application * - Typecheck for LTExpr::Application
* - typecheck & inference for rest * - typecheck & inference for rest
*/ */
@ -53,100 +57,16 @@ fn main() {
let main_scope = Scope::with_parent(&root_scope); let main_scope = Scope::with_parent(&root_scope);
let typectx = main_scope.read().unwrap().typectx.clone(); let typectx = main_scope.read().unwrap().typectx.clone();
let args: Vec<String> = std::env::args().collect();
let path = &args[1];
let iter_chars = iterate_text::file::characters::IterateFileCharacters::new(path);
/* link assembly-program to symbols /* link assembly-program to symbols
*/ */
linker.add_procedure( linker.add_procedure("main", compile(&main_scope, "main", iter_chars));
"main",
compile(
&main_scope,
"main",
"{
let print-nullterm =
λ{} : < Seq Char ~Ascii ~ machine.Word >
~ < NullTerminatedArray machine.Word >
{
while(dup) { emit; }
drop;
};
print-nullterm 'H' 'a' 'l' 'l' 'o' ' ' 'W' 'e' 'l' 't' '!' '\n' '\0';
let fmt-uint =
λx : ~ _2^64 ~ machine.UInt64
{
if( x ) {
while( x ) {
i+ '0' (i% x 10);
! x (i/ x 10);
}
} else {
'0';
};
};
let print-uint = λx: print-nullterm (fmt-uint x) '\0';
let int-neg = λx : ~ machine.Int64 ~ machine.Word i+ (bit-neg x) 1;
let int-sign = λx : ~ machine.Int64 ~ machine.Word bit-and (bit-shr x 63) 1;
let int-lt = λ{
a : ~ machine.Int64;
b : ~ machine.Int64;
} int-sign (i- a b);
let int-gt = λ{
a : ~ machine.Int64;
b : ~ machine.Int64;
} int-sign (i- b a);
let int-eq = λ{
a : ~ machine.Int64;
b : ~ machine.Int64;
} if (i- a b) { 0; } else { 1; };
let int-lte = λa: λb: bit-or (int-lt a b) (int-eq a b);
let int-gte = λa: λb: bit-or (int-gt a b) (int-eq a b);
let int-min = λ{
a : ~ machine.Int64;
b : ~ machine.Int64;
} if( int-lt a b ) { a; } else { b; };
let int-max = λ{
a : ~ machine.Int64;
b : ~ machine.Int64;
} if( int-gt a b ) { a; } else { b; };
let vec3i-add = λ{
{ ax:_2^64; ay:_2^64; az:_2^64; } : <Vec3 _2^64~machine.UInt64>;
{ bx:_2^64; by:_2^64; bz:_2^64; } : <Vec3 _2^64~machine.UInt64>;
} {
i+ az bz;
i+ ay by;
i+ ax bx;
};
let fmt-vec3i =
λ{ x:_2^64; y:_2^64; z:_2^64; } : <Vec3 _2^64~machine.UInt64>
{
'}';
fmt-uint z; '='; 'z'; ' '; ';';
fmt-uint y; '='; 'y'; ' '; ';';
fmt-uint x; '='; 'x'; '{';
};
let red-u8rgb
: <Fn <> Color ~ RGB ~ <Vec3 _0,1 ~ _256 ~ machine.UInt64>>
= λ{} { 0; 0; 255; };
let green-u8rgb = λ{} { 0; 255; 0; };
let blue-u8rgb = λ{} { 255; 0; 0; };
let yellow-u8rgb = λ{} { 0; 220; 220; };
print-nullterm (fmt-vec3i (vec3i-add green-u8rgb blue-u8rgb)) '\n' '\0';
}"
),
);
/* load & run compiled bytecode
*/
let main_addr = linker let main_addr = linker
.get_link_addr(&"main".into()) .get_link_addr(&"main".into())
.expect("'main' not linked"); .expect("'main' not linked");

View file

@ -1,7 +1,7 @@
use { use {
crate::{ crate::{
expr::{LTExpr, Statement, TypeError, TypeTag}, expr::{LTExpr, Statement, TypeError, TypeTag},
lexer::{LTIRLexer, LTIRToken, LexError}, lexer::{LTIRLexer, LTIRToken, LexError, InputRegionTag},
}, },
std::{ std::{
iter::Peekable, iter::Peekable,
@ -19,11 +19,10 @@ pub enum ParseError {
} }
pub fn parse_expect<It>( pub fn parse_expect<It>(
tokens: &mut Peekable<LTIRLexer<It>>, tokens: &mut Peekable<It>,
expected_token: LTIRToken, expected_token: LTIRToken,
) -> Result<(), ParseError> ) -> Result<(), ParseError>
where where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
It: Iterator<Item = char>,
{ {
match tokens.next() { match tokens.next() {
Some((region, Ok(t))) => { Some((region, Ok(t))) => {
@ -40,9 +39,8 @@ where
/* parse symbol name /* parse symbol name
*/ */
pub fn parse_symbol<It>(tokens: &mut Peekable<LTIRLexer<It>>) -> Result<String, ParseError> pub fn parse_symbol<It>(tokens: &mut Peekable<It>) -> Result<String, ParseError>
where where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
It: Iterator<Item = char>,
{ {
match tokens.next() { match tokens.next() {
Some((region, Ok(LTIRToken::Symbol(name)))) => Ok(name), Some((region, Ok(LTIRToken::Symbol(name)))) => Ok(name),
@ -57,10 +55,9 @@ where
*/ */
pub fn parse_type_tag<It>( pub fn parse_type_tag<It>(
typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>, typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>,
tokens: &mut Peekable<LTIRLexer<It>>, tokens: &mut Peekable<It>,
) -> Result<Option<laddertypes::TypeTerm>, ParseError> ) -> Result<Option<laddertypes::TypeTerm>, ParseError>
where where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
It: Iterator<Item = char>,
{ {
if let Some((region, peektok)) = tokens.peek().clone() { if let Some((region, peektok)) = tokens.peek().clone() {
match peektok.clone() { match peektok.clone() {
@ -111,9 +108,9 @@ impl VariableBinding {
*/ */
pub fn parse_binding_expr<It>( pub fn parse_binding_expr<It>(
typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>, typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>,
tokens: &mut Peekable<LTIRLexer<It>>, tokens: &mut Peekable<It>,
) -> Result< VariableBinding, ParseError> ) -> Result< VariableBinding, ParseError>
where It: Iterator<Item = char> where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
{ {
if let Some((region, peektok)) = tokens.peek().clone() { if let Some((region, peektok)) = tokens.peek().clone() {
match peektok { match peektok {
@ -142,10 +139,9 @@ where It: Iterator<Item = char>
*/ */
pub fn parse_binding_block<It>( pub fn parse_binding_block<It>(
typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>, typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>,
tokens: &mut Peekable<LTIRLexer<It>>, tokens: &mut Peekable<It>,
) -> Result< Vec<VariableBinding>, ParseError> ) -> Result< Vec<VariableBinding>, ParseError>
where where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
It: Iterator<Item = char>,
{ {
let _ = parse_expect(tokens, LTIRToken::BlockOpen)?; let _ = parse_expect(tokens, LTIRToken::BlockOpen)?;
@ -173,10 +169,9 @@ where
pub fn parse_statement<It>( pub fn parse_statement<It>(
typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>, typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>,
tokens: &mut Peekable<LTIRLexer<It>>, tokens: &mut Peekable<It>,
) -> Result<crate::expr::Statement, ParseError> ) -> Result<crate::expr::Statement, ParseError>
where where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
It: Iterator<Item = char>,
{ {
if let Some((region, peektok)) = tokens.peek() { if let Some((region, peektok)) = tokens.peek() {
match peektok { match peektok {
@ -251,10 +246,9 @@ where
pub fn parse_statement_block<It>( pub fn parse_statement_block<It>(
typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>, typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>,
tokens: &mut Peekable<LTIRLexer<It>>, tokens: &mut Peekable<It>,
) -> Result<Vec<Statement>, ParseError> ) -> Result<Vec<Statement>, ParseError>
where where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
It: Iterator<Item = char>,
{ {
let _ = parse_expect(tokens, LTIRToken::BlockOpen)?; let _ = parse_expect(tokens, LTIRToken::BlockOpen)?;
@ -278,10 +272,9 @@ where
} }
pub fn parse_atom<It>( pub fn parse_atom<It>(
tokens: &mut Peekable<LTIRLexer<It>>, tokens: &mut Peekable<It>,
) -> Result<crate::expr::LTExpr, ParseError> ) -> Result<crate::expr::LTExpr, ParseError>
where where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
It: Iterator<Item = char>,
{ {
match tokens.next() { match tokens.next() {
Some((region, Ok(LTIRToken::Symbol(sym)))) => Ok(LTExpr::symbol(sym.as_str())), Some((region, Ok(LTIRToken::Symbol(sym)))) => Ok(LTExpr::symbol(sym.as_str())),
@ -295,10 +288,9 @@ where
pub fn parse_expr<It>( pub fn parse_expr<It>(
typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>, typectx: &Arc<RwLock<laddertypes::dict::TypeDict>>,
tokens: &mut Peekable<LTIRLexer<It>>, tokens: &mut Peekable<It>,
) -> Result<crate::expr::LTExpr, ParseError> ) -> Result<crate::expr::LTExpr, ParseError>
where where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
It: Iterator<Item = char>,
{ {
let mut children = Vec::new(); let mut children = Vec::new();