add export block and ability to load multiple files
This commit is contained in:
parent
f06bf14b52
commit
8d19767c98
13 changed files with 439 additions and 245 deletions
47
lt-stdlib/color.lt
Normal file
47
lt-stdlib/color.lt
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
export {
|
||||||
|
let morph-rgb-to-hsv = λ{
|
||||||
|
{
|
||||||
|
red: ℝ_0,1 ~ ℤ_256 ~ machine.UInt64;
|
||||||
|
green: ℝ_0,1 ~ ℤ_256 ~ machine.UInt64;
|
||||||
|
blue: ℝ_0,1 ~ ℤ_256 ~ machine.UInt64;
|
||||||
|
} : <Color sRGB>
|
||||||
|
~ RGB
|
||||||
|
~ <Vec3 ℝ_0,1 ~ ℤ_256 ~ machine.UInt64>;
|
||||||
|
/*
|
||||||
|
::> Color
|
||||||
|
~ HSV
|
||||||
|
~ {
|
||||||
|
hue: Angle
|
||||||
|
~ Degrees
|
||||||
|
~ ℝ_0,360
|
||||||
|
~ ℤ_360
|
||||||
|
~ machine.UInt64 ;
|
||||||
|
|
||||||
|
saturation: ℝ_0,1 ~ ℤ_256 ~ machine.UInt64 ;
|
||||||
|
value: ℝ_0,1 ~ ℤ_256 ~ machine.UInt64 ;
|
||||||
|
}
|
||||||
|
~ <Vec3 machine.UInt64>
|
||||||
|
*/
|
||||||
|
} ↦ {
|
||||||
|
let channel_max = int-max (int-max red green) blue;
|
||||||
|
let channel_min = int-min (int-min red green) blue;
|
||||||
|
|
||||||
|
/* value */
|
||||||
|
channel_max;
|
||||||
|
|
||||||
|
/* saturation */
|
||||||
|
i/ (i* 255 (i- channel_max channel_min)) channel_max;
|
||||||
|
|
||||||
|
/* hue */
|
||||||
|
i% (i/ (i* 60
|
||||||
|
if( int-eq channel_max red ) { i+ (i* 0 255) (i- green blue); }
|
||||||
|
else {
|
||||||
|
if( int-eq channel_max green ) { i+ (i* 2 255) (i- blue red); }
|
||||||
|
else { i+ (i* 4 255) (i- red green); };
|
||||||
|
}
|
||||||
|
)
|
||||||
|
(i- channel_max channel_min)
|
||||||
|
)
|
||||||
|
360;
|
||||||
|
};
|
||||||
|
}
|
28
lt-stdlib/euclidean.lt
Normal file
28
lt-stdlib/euclidean.lt
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
|
||||||
|
/* Integer Math
|
||||||
|
*/
|
||||||
|
|
||||||
|
export {
|
||||||
|
/* 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));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
18
lt-stdlib/int.lt
Normal file
18
lt-stdlib/int.lt
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
|
||||||
|
/* Two's complement Signed Integers
|
||||||
|
*/
|
||||||
|
|
||||||
|
export {
|
||||||
|
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 (bit-xor 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; };
|
||||||
|
};
|
||||||
|
|
63
lt-stdlib/posint.lt
Normal file
63
lt-stdlib/posint.lt
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
|
||||||
|
|
||||||
|
/* Positional Integer
|
||||||
|
*/
|
||||||
|
export {
|
||||||
|
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 uint-machine-to-posint =
|
||||||
|
λ{
|
||||||
|
radix: ℕ ~ ℤ_2^64 ~ machine.UInt64;
|
||||||
|
value: ℕ ~ ℤ_2^64 ~ machine.UInt64;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
::> ℕ
|
||||||
|
~ <PosInt radix BigEndian>
|
||||||
|
~ <Seq <Digit radix>
|
||||||
|
~ ℤ_radix
|
||||||
|
~ ℤ_2^64
|
||||||
|
~ machine.UInt64>
|
||||||
|
~ <LengthPrefixedArray machine.UInt64>
|
||||||
|
*/
|
||||||
|
↦ {
|
||||||
|
let len = 0;
|
||||||
|
while( value ) {
|
||||||
|
/* push digit to sequence on stack */
|
||||||
|
i% value radix;
|
||||||
|
! value (i/ value radix);
|
||||||
|
! len (i+ len 1);
|
||||||
|
}
|
||||||
|
/* push length of sequence to stack */
|
||||||
|
len;
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
45
lt-stdlib/ratio.lt
Normal file
45
lt-stdlib/ratio.lt
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
export {
|
||||||
|
/* 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 fmt-ratio = λ{ p:ℤ; q:ℤ; }: ℚ~<Ratio ℤ> ↦ {
|
||||||
|
fmt-int q;':';fmt-int p;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
12
lt-stdlib/stdio.lt
Normal file
12
lt-stdlib/stdio.lt
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
export {
|
||||||
|
/* output nullterminated string directly from datastack
|
||||||
|
*/
|
||||||
|
let print-nullterm =
|
||||||
|
λ{} : < Seq Char~Ascii~machine.Word >
|
||||||
|
~ < NullTerminatedArray machine.Word >
|
||||||
|
↦ {
|
||||||
|
while(dup) { emit; }
|
||||||
|
drop;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
23
lt-stdlib/vec3i.lt
Normal file
23
lt-stdlib/vec3i.lt
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
export {
|
||||||
|
/* 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'; '{';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
198
main.lt
198
main.lt
|
@ -1,182 +1,18 @@
|
||||||
{
|
{
|
||||||
/*
|
print-nullterm 'H''e''l''l''o'' ''W''o''r''l''d''!''\n''\0';
|
||||||
* 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
|
/* test ratio
|
||||||
*/
|
*/
|
||||||
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
|
print-nullterm
|
||||||
(fmt-ratio { 4; int-neg 3; })
|
(fmt-ratio { 4; int-neg 3; })
|
||||||
' ''*'' '
|
' ''*'' '
|
||||||
(fmt-ratio { 7; 4; })
|
(fmt-ratio { 7; 4; })
|
||||||
' ''='' '
|
' ''='' '
|
||||||
(fmt-ratio (ratio-mul { 4; int-neg 3; } { 7; 4; }))
|
(fmt-ratio (ratio-mul { 4; int-neg 3; } { 7; 4; }))
|
||||||
'\n''\0';
|
'\n''\0';
|
||||||
|
|
||||||
|
/* Colors
|
||||||
/* 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
|
let red-u8rgb
|
||||||
: <Fn <> Color ~ RGB ~ <Vec3 ℝ_0,1 ~ ℤ_256 ~ machine.UInt64>>
|
: <Fn <> Color ~ RGB ~ <Vec3 ℝ_0,1 ~ ℤ_256 ~ machine.UInt64>>
|
||||||
= λ{} ↦ { 0; 0; 255; };
|
= λ{} ↦ { 0; 0; 255; };
|
||||||
|
@ -185,12 +21,16 @@
|
||||||
let blue-u8rgb = λ{} ↦ { 255; 0; 0; };
|
let blue-u8rgb = λ{} ↦ { 255; 0; 0; };
|
||||||
let yellow-u8rgb = λ{} ↦ { 0; 220; 220; };
|
let yellow-u8rgb = λ{} ↦ { 0; 220; 220; };
|
||||||
|
|
||||||
print-nullterm
|
print-nullterm (fmt-vec3i (morph-rgb-to-hsv yellow-u8rgb)) '\n''\0';
|
||||||
(fmt-vec3i green-u8rgb)
|
|
||||||
' ''+'' '
|
print-nullterm
|
||||||
(fmt-vec3i blue-u8rgb)
|
(fmt-vec3i green-u8rgb)
|
||||||
' ''='' '
|
' ''+'' '
|
||||||
|
(fmt-vec3i blue-u8rgb)
|
||||||
|
' ''='' '
|
||||||
(fmt-vec3i (vec3i-add green-u8rgb blue-u8rgb))
|
(fmt-vec3i (vec3i-add green-u8rgb blue-u8rgb))
|
||||||
'\n''\0';
|
'\n''\0';
|
||||||
|
|
||||||
|
uint-machine-to-posint 16 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,9 @@ pub enum LTExpr {
|
||||||
Block {
|
Block {
|
||||||
statements: Vec<Statement>,
|
statements: Vec<Statement>,
|
||||||
},
|
},
|
||||||
|
ExportBlock {
|
||||||
|
statements: Vec<Statement>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LTExpr {
|
impl LTExpr {
|
||||||
|
|
87
src/main.rs
87
src/main.rs
|
@ -76,8 +76,10 @@ fn print_diagnostic(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO:
|
/* TODO:
|
||||||
|
* - export / import , load multiple files
|
||||||
* - Compiler error reporting
|
* - Compiler error reporting
|
||||||
* - parse float literals
|
* - parse float literals
|
||||||
|
* - return type annotation
|
||||||
* - write to address resulting from expression
|
* - write to address resulting from expression
|
||||||
* - sized objects
|
* - sized objects
|
||||||
* - Typecheck for LTExpr::Application
|
* - Typecheck for LTExpr::Application
|
||||||
|
@ -96,8 +98,17 @@ fn main() {
|
||||||
/* open source file
|
/* open source file
|
||||||
*/
|
*/
|
||||||
let args: Vec<String> = std::env::args().collect();
|
let args: Vec<String> = std::env::args().collect();
|
||||||
let path = &args[1];
|
|
||||||
let iter_chars = iterate_text::file::characters::IterateFileCharacters::new(path);
|
if args.len() < 2 {
|
||||||
|
eprintln!("{}", "No source files specified.".red());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut args_iter = args.into_iter();
|
||||||
|
args_iter.next();
|
||||||
|
|
||||||
|
for path in args_iter {
|
||||||
|
let iter_chars = iterate_text::file::characters::IterateFileCharacters::new(path.clone());
|
||||||
|
|
||||||
/* compile source file
|
/* compile source file
|
||||||
*/
|
*/
|
||||||
|
@ -108,40 +119,54 @@ fn main() {
|
||||||
})
|
})
|
||||||
.peekable();
|
.peekable();
|
||||||
|
|
||||||
match parser::parse_expr( &typectx, &mut program_tokens ) {
|
match parser::parse_expr( &typectx, &mut program_tokens ) {
|
||||||
Ok( ast ) => {
|
Ok( ast ) => {
|
||||||
let bytecode = ProcedureCompiler::new(&main_scope)
|
let (exports, bytecode) = ProcedureCompiler::new(&main_scope)
|
||||||
.compile( &ast )
|
.compile(&ast)
|
||||||
.into_asm(&"main".into());
|
.into_asm(&path);
|
||||||
|
|
||||||
eprintln!("{}", "Compiled successfully.\n======================\n".green());
|
eprintln!("{} {}", "Compiled".green(), path.bold());
|
||||||
|
for (name, def) in exports.iter() {
|
||||||
|
eprintln!("export {}: {:?}", name.yellow().bold(), def);
|
||||||
|
}
|
||||||
|
|
||||||
/* link assembly-program to symbols
|
main_scope.write().unwrap().import(
|
||||||
*/
|
exports
|
||||||
linker.add_procedure("main", bytecode);
|
);
|
||||||
|
|
||||||
/* load & run compiled bytecode
|
/* link assembly-program to symbols
|
||||||
*/
|
*/
|
||||||
let main_addr = linker
|
linker.add_procedure(path.as_str(), bytecode);
|
||||||
.get_link_addr(&"main".into())
|
}
|
||||||
.expect("'main' not linked");
|
Err( (region, parse_error) ) => {
|
||||||
|
print_diagnostic(
|
||||||
|
path.as_str(),
|
||||||
|
region,
|
||||||
|
format!("{:?}", parse_error)
|
||||||
|
);
|
||||||
|
|
||||||
vm.load(linker.link_total().expect("could not link"));
|
eprintln!("=======\nParse Error: Abort\n");
|
||||||
vm.execute(main_addr);
|
}
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
"\n====\nVM execution finished\ndatastack = {:?}\n====",
|
|
||||||
vm.data_stack
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Err( (region, parse_error) ) => {
|
|
||||||
print_diagnostic(
|
|
||||||
path,
|
|
||||||
region,
|
|
||||||
format!("{:?}", parse_error)
|
|
||||||
);
|
|
||||||
|
|
||||||
eprintln!("=======\nerror: Parse Error\n");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/* load & run compiled bytecode
|
||||||
|
*/
|
||||||
|
let main_addr = linker
|
||||||
|
.get_link_addr(&"main.lt".into())
|
||||||
|
.expect("'main.lt' not found");
|
||||||
|
|
||||||
|
let bytecode = linker.link_total().expect("Link error:");
|
||||||
|
|
||||||
|
eprintln!("{} ({} bytes)", "Linked bytecode.".green(), bytecode.len());
|
||||||
|
eprintln!("================\n");
|
||||||
|
|
||||||
|
vm.load(bytecode);
|
||||||
|
vm.execute(main_addr);
|
||||||
|
|
||||||
|
eprintln!(
|
||||||
|
"\n================\nVM execution finished\ndatastack = {:?}\n====",
|
||||||
|
vm.data_stack
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ impl VariableBinding {
|
||||||
.flatten()
|
.flatten()
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse a symbol binding of the form
|
/* parse a symbol binding of the form
|
||||||
|
@ -364,7 +364,14 @@ where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
|
||||||
if_expr: Box::new(if_expr),
|
if_expr: Box::new(if_expr),
|
||||||
else_expr: Box::new(else_expr),
|
else_expr: Box::new(else_expr),
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
"export" => {
|
||||||
|
tokens.next();
|
||||||
|
let block = parse_statement_block(typectx, tokens)?;
|
||||||
|
children.push(LTExpr::ExportBlock {
|
||||||
|
statements: block
|
||||||
|
});
|
||||||
|
},
|
||||||
name => {
|
name => {
|
||||||
children.push(parse_atom(tokens)?);
|
children.push(parse_atom(tokens)?);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct ProcedureCompiler {
|
pub struct ProcedureCompiler {
|
||||||
symbols: Arc<RwLock<Scope>>,
|
pub symbols: Arc<RwLock<Scope>>,
|
||||||
asm: tisc::Assembler,
|
asm: tisc::Assembler,
|
||||||
linker: tisc::Linker,
|
linker: tisc::Linker,
|
||||||
result_size: usize,
|
result_size: usize,
|
||||||
|
@ -27,8 +27,17 @@ impl ProcedureCompiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_asm(mut self, proc_symbol: &String) -> Vec<tisc::assembler::AssemblyWord> {
|
pub fn into_asm(mut self, proc_symbol: &String) -> (Vec<(String, SymbolDef)>, Vec<tisc::assembler::AssemblyWord>) {
|
||||||
let data_frame_size = self.symbols.read().unwrap().get_frame_size() as i64;
|
let mut symbols =
|
||||||
|
Arc::try_unwrap(self.symbols).ok().unwrap()
|
||||||
|
.into_inner().unwrap();
|
||||||
|
|
||||||
|
symbols.update_link_addresses(
|
||||||
|
proc_symbol,
|
||||||
|
&self.linker
|
||||||
|
);
|
||||||
|
|
||||||
|
let data_frame_size = symbols.get_frame_size() as i64;
|
||||||
|
|
||||||
let body = self.asm.build();
|
let body = self.asm.build();
|
||||||
self.linker.add_procedure("__procedure_body__", body);
|
self.linker.add_procedure("__procedure_body__", body);
|
||||||
|
@ -36,6 +45,7 @@ impl ProcedureCompiler {
|
||||||
.linker
|
.linker
|
||||||
.get_link_addr(&"__procedure_body__".into())
|
.get_link_addr(&"__procedure_body__".into())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let subroutines = self
|
let subroutines = self
|
||||||
.linker
|
.linker
|
||||||
.link_relative(&"__subroutines__".into())
|
.link_relative(&"__subroutines__".into())
|
||||||
|
@ -58,21 +68,37 @@ impl ProcedureCompiler {
|
||||||
superlink.add_procedure("", entry.build());
|
superlink.add_procedure("", entry.build());
|
||||||
superlink.add_procedure("__subroutines__", subroutines);
|
superlink.add_procedure("__subroutines__", subroutines);
|
||||||
|
|
||||||
let bytecode = superlink.link_relative(proc_symbol).expect("link error");
|
symbols.update_link_addresses(
|
||||||
/*
|
&proc_symbol,
|
||||||
eprintln!("\n\n{}:", proc_symbol);
|
&superlink
|
||||||
for (i,w) in tisc::assembler::disassemble(&bytecode).iter().enumerate() {
|
);
|
||||||
eprintln!("{}:\t\t{}", i, w);
|
|
||||||
|
let mut symbol_exports = symbols.export();
|
||||||
|
let subroutines_addr = superlink.get_link_addr(&"__subroutines__".into()).unwrap();
|
||||||
|
for (name, def) in symbol_exports.iter_mut() {
|
||||||
|
match def {
|
||||||
|
SymbolDef::Procedure{ in_types:_, out_types:_, link_addr, export:_ } => {
|
||||||
|
match link_addr {
|
||||||
|
LinkAddr::Relative{ symbol, offset } => {
|
||||||
|
*offset += subroutines_addr;
|
||||||
|
}
|
||||||
|
LinkAddr::Absolute(addr) => {
|
||||||
|
*addr += subroutines_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
_ => {}
|
||||||
bytecode
|
}
|
||||||
|
}
|
||||||
|
let bytecode = superlink.link_relative(proc_symbol).expect("link error");
|
||||||
|
(symbol_exports, bytecode)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify(&self) {
|
pub fn verify(&self) {
|
||||||
// todo
|
// todo
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_statement(mut self, statement: &Statement) -> Self {
|
pub fn compile_statement(mut self, statement: &Statement, enable_export: bool) -> Self {
|
||||||
match statement {
|
match statement {
|
||||||
Statement::Assignment { var_id, val_expr } => {
|
Statement::Assignment { var_id, val_expr } => {
|
||||||
self = self.compile(val_expr);
|
self = self.compile(val_expr);
|
||||||
|
@ -91,6 +117,7 @@ impl ProcedureCompiler {
|
||||||
in_types,
|
in_types,
|
||||||
out_types,
|
out_types,
|
||||||
link_addr,
|
link_addr,
|
||||||
|
export
|
||||||
}) => {
|
}) => {
|
||||||
self.asm = self
|
self.asm = self
|
||||||
.asm
|
.asm
|
||||||
|
@ -111,12 +138,23 @@ impl ProcedureCompiler {
|
||||||
self.symbols
|
self.symbols
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.declare_proc(var_id.clone(), vec![], vec![]);
|
.declare_proc(var_id.clone(), vec![], vec![], enable_export);
|
||||||
let lambda_procedure = ProcedureCompiler::new(&self.symbols)
|
|
||||||
|
let (exports, lambda_procedure) = ProcedureCompiler::new(&self.symbols)
|
||||||
.compile(val_expr)
|
.compile(val_expr)
|
||||||
.into_asm(var_id);
|
.into_asm(var_id);
|
||||||
|
|
||||||
self.linker.add_procedure(var_id, lambda_procedure);
|
self.linker.add_procedure(var_id, lambda_procedure);
|
||||||
|
|
||||||
|
let offset = self.linker.get_link_addr(var_id).unwrap();
|
||||||
|
|
||||||
|
if enable_export {
|
||||||
|
for (name, def) in exports.iter() {
|
||||||
|
eprintln!("Procedure compiler: export {}", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.symbols.write().unwrap().import( exports );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.symbols
|
self.symbols
|
||||||
|
@ -126,7 +164,7 @@ impl ProcedureCompiler {
|
||||||
self = self.compile_statement(&Statement::Assignment {
|
self = self.compile_statement(&Statement::Assignment {
|
||||||
var_id: var_id.clone(),
|
var_id: var_id.clone(),
|
||||||
val_expr: val_expr.clone(),
|
val_expr: val_expr.clone(),
|
||||||
});
|
}, false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Statement::WhileLoop { condition, body } => {
|
Statement::WhileLoop { condition, body } => {
|
||||||
|
@ -138,7 +176,7 @@ impl ProcedureCompiler {
|
||||||
|
|
||||||
self.asm = tisc::Assembler::new();
|
self.asm = tisc::Assembler::new();
|
||||||
for statement in body.into_iter() {
|
for statement in body.into_iter() {
|
||||||
self = self.compile_statement(statement);
|
self = self.compile_statement(statement, false);
|
||||||
}
|
}
|
||||||
let body_asm = self.asm;
|
let body_asm = self.asm;
|
||||||
|
|
||||||
|
@ -168,8 +206,9 @@ impl ProcedureCompiler {
|
||||||
in_types,
|
in_types,
|
||||||
out_types,
|
out_types,
|
||||||
link_addr,
|
link_addr,
|
||||||
|
export
|
||||||
}) => {
|
}) => {
|
||||||
self.asm = self.asm.call(symbol.as_str());
|
self.asm = self.asm.call_symbol(link_addr);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
eprintln!("undefined symbol '{}'!", symbol);
|
eprintln!("undefined symbol '{}'!", symbol);
|
||||||
|
@ -218,7 +257,12 @@ impl ProcedureCompiler {
|
||||||
}
|
}
|
||||||
LTExpr::Block { statements } => {
|
LTExpr::Block { statements } => {
|
||||||
for s in statements.iter() {
|
for s in statements.iter() {
|
||||||
self = self.compile_statement(s);
|
self = self.compile_statement(s, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LTExpr::ExportBlock{ statements } => {
|
||||||
|
for s in statements.iter() {
|
||||||
|
self = self.compile_statement(s, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ use {
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
},
|
},
|
||||||
|
tisc::linker::LinkAddr,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -19,7 +20,8 @@ pub enum SymbolDef {
|
||||||
Procedure {
|
Procedure {
|
||||||
in_types: Vec<laddertypes::TypeTerm>,
|
in_types: Vec<laddertypes::TypeTerm>,
|
||||||
out_types: Vec<laddertypes::TypeTerm>,
|
out_types: Vec<laddertypes::TypeTerm>,
|
||||||
link_addr: Option<tisc::VM_Word>,
|
link_addr: LinkAddr,
|
||||||
|
export: bool
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +37,7 @@ impl SymbolDef {
|
||||||
in_types,
|
in_types,
|
||||||
out_types,
|
out_types,
|
||||||
link_addr: _,
|
link_addr: _,
|
||||||
|
export: _,
|
||||||
} => laddertypes::TypeTerm::App(vec![
|
} => laddertypes::TypeTerm::App(vec![
|
||||||
typectx
|
typectx
|
||||||
.write()
|
.write()
|
||||||
|
@ -94,6 +97,24 @@ impl Scope {
|
||||||
Arc::new(RwLock::new(s))
|
Arc::new(RwLock::new(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn export(self) -> Vec<(String, SymbolDef)> {
|
||||||
|
self.symbols
|
||||||
|
.into_iter()
|
||||||
|
.filter(|(name, def)|
|
||||||
|
match def {
|
||||||
|
SymbolDef::Procedure { in_types:_, out_types:_, link_addr:_, export } => *export,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn import(&mut self, symbol_imports: Vec<(String, SymbolDef)>) {
|
||||||
|
for (name, def) in symbol_imports {
|
||||||
|
self.symbols.insert( name, def );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_frame_size(&self) -> usize {
|
pub fn get_frame_size(&self) -> usize {
|
||||||
self.frame_size
|
self.frame_size
|
||||||
}
|
}
|
||||||
|
@ -116,20 +137,35 @@ impl Scope {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
pub fn get_link_addr(&self, name: &str) -> Option<tisc::VM_Word> {
|
/// takes the link-addresses from a Linker
|
||||||
match self.get(name) {
|
/// and updates the symbol table to relative addresses
|
||||||
Some(SymbolDef::Procedure{ in_types:_, out_types:_, link_addr }) => {
|
/// based on the next super-label
|
||||||
link_addr
|
pub fn update_link_addresses(
|
||||||
|
&mut self,
|
||||||
|
base_symbol: &String,
|
||||||
|
linker: &tisc::Linker
|
||||||
|
) {
|
||||||
|
for (name, def) in self.symbols.iter_mut() {
|
||||||
|
if let Some(offset) = linker.get_link_addr( name ) {
|
||||||
|
match def {
|
||||||
|
SymbolDef::Procedure {
|
||||||
|
in_types:_,out_types:_,
|
||||||
|
link_addr,
|
||||||
|
export:_
|
||||||
|
} => {
|
||||||
|
*link_addr = LinkAddr::Relative{
|
||||||
|
symbol: base_symbol.clone(),
|
||||||
|
offset
|
||||||
|
};
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
Some(SymbolDef::StaticRef { typ:_, link_addr }) => {
|
|
||||||
link_addr
|
|
||||||
}
|
|
||||||
Some(SymbolDef::FrameRef { typ:_, stack_ref:_ }) => None,
|
|
||||||
None => None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
}
|
||||||
|
|
||||||
|
|
||||||
//<><><><><><>
|
//<><><><><><>
|
||||||
|
|
||||||
pub fn declare_proc_parse(
|
pub fn declare_proc_parse(
|
||||||
|
@ -165,6 +201,7 @@ impl Scope {
|
||||||
.expect("parse typeterm")
|
.expect("parse typeterm")
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,13 +210,15 @@ impl Scope {
|
||||||
name: String,
|
name: String,
|
||||||
in_types: Vec<laddertypes::TypeTerm>,
|
in_types: Vec<laddertypes::TypeTerm>,
|
||||||
out_types: Vec<laddertypes::TypeTerm>,
|
out_types: Vec<laddertypes::TypeTerm>,
|
||||||
|
export: bool
|
||||||
) {
|
) {
|
||||||
self.symbols.insert(
|
self.symbols.insert(
|
||||||
name,
|
name.clone(),
|
||||||
SymbolDef::Procedure {
|
SymbolDef::Procedure {
|
||||||
link_addr: None, //LinkAddr::Relative{ name, offset: 0 },
|
link_addr: LinkAddr::Relative{ symbol: name, offset: 0 },
|
||||||
in_types,
|
in_types,
|
||||||
out_types,
|
out_types,
|
||||||
|
export
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue