diff --git a/fetch.lt b/fetch.lt new file mode 100644 index 0000000..b7045bd --- /dev/null +++ b/fetch.lt @@ -0,0 +1,31 @@ + +export { + let fetch-word : + &machine.Word ~ ~ machine.Address ~ machine.UInt64 + -> machine.Word; + + let fetch-byte : + & + ~ + ~ machine.Address + ~ machine.UInt64 + -> + ~ machine.Word + = λ ptr ↦ { + fetch-word (align ptr); + bit-shr (* 8 (ptr % 8)); + bit-and 0xff; + }; + + let fetch-nibble + : & + ~ + ~ machine.UInt64 + + -> + ~ machine.Word + = λ idx ↦ { + + }; +} + diff --git a/lt-stdlib/angle.lt b/lt-stdlib/angle.lt new file mode 100644 index 0000000..c29dbe0 --- /dev/null +++ b/lt-stdlib/angle.lt @@ -0,0 +1,19 @@ +export { + let angle-normalize = + λ a : Angle + ~ Degree + ~ ℝ_0,360 + ~ ℤ_360 + ~ ℤ_2^64 + ~ machine.UInt64 + ~ machine.Word + ↦ Angle~Degree~ℝ_0,360~ℤ_360: machine.UInt64.rem a 360; + + let angle-degree-to-turns = + λ a : Angle + ~ Degree + ~ ℝ_0,360 + ~ ℝ + ~ machine.Float64 + ↦ f/ a 360 ; +} diff --git a/lt-stdlib/color.lt b/lt-stdlib/color.lt index 84e9bc4..906ecca 100644 --- a/lt-stdlib/color.lt +++ b/lt-stdlib/color.lt @@ -1,36 +1,35 @@ export { + /* todo: allow machine.UInt8 in the VM + */ let morph-rgb-to-hsv = λ{ { - red: ℝ_0,1 ~ ℤ_256 ~ machine.UInt64; - green: ℝ_0,1 ~ ℤ_256 ~ machine.UInt64; - blue: ℝ_0,1 ~ ℤ_256 ~ machine.UInt64; + red: ℝ_[0,1] ~ ℤ_256 ~ machine.UInt64; + green: ℝ_[0,1] ~ ℤ_256 ~ machine.UInt64; + blue: ℝ_[0,1] ~ ℤ_256 ~ machine.UInt64; } : ~ RGB - ~ ; - /* - ::> Color - ~ HSV - ~ { - hue: Angle - ~ Degrees - ~ ℝ_0,360 - ~ ℤ_360 - ~ machine.UInt64 ; - - saturation: ℝ_0,1 ~ ℤ_256 ~ machine.UInt64 ; - value: ℝ_0,1 ~ ℤ_256 ~ machine.UInt64 ; - } - ~ - */ - } ↦ { + ~ ; + } + /* + -> + ~ HSV + ~ { + hue: Angle ~ Degrees ~ ℝ_0,360 ~ ℤ_360 ~ machine.UInt64 ; + sat: ℝ_[0,1] ~ ℤ_256 ~ machine.UInt64; + val: ℝ_[0,1] ~ ℤ_256 ~ machine.UInt64; + } + ~ + */ + ↦ { let channel_max = int-max (int-max red green) blue; let channel_min = int-min (int-min red green) blue; + let channel_delta = i- channel_max channel_min; - /* value */ + /* value */ channel_max; /* saturation */ - i/ (i* 255 (i- channel_max channel_min)) channel_max; + i/ (i* 255 channel_delta) channel_max; /* hue */ i% (i/ (i* 60 @@ -40,8 +39,25 @@ export { else { i+ (i* 4 255) (i- red green); }; } ) - (i- channel_max channel_min) + channel_delta ) 360; - }; + }; + +/* + let get-srgb-luminance = + -> ℝ_[0,1] ~ machine.Float64 + λ{r:ℝ,g:ℝ,b:ℝ} : ~ RGB ~ + ↦ + { + machine.Float64.mul red 0.22248840; + machine.Float64.mul green 0.71690369; + machine.Float64.mul blue 0.06060791; + machine.Float64.add; + machine.Float64.add; + +// add (add (mul r 0.2) (mul g 0.7)) (mul b 0.6) + }; +*/ } + diff --git a/lt-stdlib/complex.lt b/lt-stdlib/complex.lt new file mode 100644 index 0000000..4caba45 --- /dev/null +++ b/lt-stdlib/complex.lt @@ -0,0 +1,10 @@ +export { + let complex-magnitude = λ{ + { re: ℝ, im: ℝ } + : ℂ + ~ Cartesian + ~ + } -> ℝ ↦ { + + } +} diff --git a/lt-stdlib/float.lt b/lt-stdlib/float.lt new file mode 100644 index 0000000..c4e5e16 --- /dev/null +++ b/lt-stdlib/float.lt @@ -0,0 +1,61 @@ +export { + /* Platform Specific Types */ + type machine.Float16 = IEEE-754.half ~ ; + type machine.Float32 = IEEE-754.single ~ ; + type machine.Float64 = IEEE-754.double ~ ; + + overload + = λ{ + a:ℝ ~ machine.Float16 ; + b:ℝ ~ machine.Float16 ; + } -> ℝ ~ machine.Float16 ↦ { + machine.Float16.add a b; + }; + + overload * = λ{ + a:ℝ ~ machine.Float16 ; + b:ℝ ~ machine.Float16 ; + } -> ℝ ~ machine.Float16 ↦ { + machine.Float16.mul a b; + }; + + let Sign = enum { Positive; Negative; }; + let Sign.Positive : = 0; + let Sign.Negative : = 1; + + let softfloat16-mul = λ{ + { + a.sign: Sign + ~ + ; + a.exponent: ℤ_[-14,15] + ~ + ~ ℤ_32 + ~ + ~ ~Bit > + ~ + ; + a.significand: ℤ_2048 + ~ + ~ ~ Bit> + ~ + ; + } : ℝ + ~ IEEE-754.Half + ~ + ; + { + b.sign: ; + } : ℝ ~ IEEE-754.Half ~ ; + } -> result: ℝ ~ IEEE~754.Half ~ ↦ { + + /* 1. unify */ + + /* 2. add exponent */ + + a.exponent b.exponent; + + /* 3. normaize */ + + result.sign = bit-xor a.sign b.sign ; + } +} + diff --git a/lt-stdlib/image.lt b/lt-stdlib/image.lt new file mode 100644 index 0000000..36fd73a --- /dev/null +++ b/lt-stdlib/image.lt @@ -0,0 +1,138 @@ +/* C++ */ + +template +struct Sample { + T value; +}; + +template<> struct Sample< uint8_t > { + constexpr uint8_t min = std::numeric_limits::min(); + constexpr uint8_t max = std::numeric_limits::max(); +}; +template<> struct Sample< uint16_t > { + constexpr uint16_t min = std::numeric_limits::min(); + constexpr uint16_t max = std::numeric_limits::max(); +}; +template<> struct Sample< uint32_t > { + constexpr uint32_t min = std::numeric_limits::min(); + constexpr uint32_t max = std::numeric_limits::max(); +}; +template<> struct Sample< float > { + constexpr float min = 0.0; + constexpr float max = 1.0; +}; +template<> struct Sample< double > { + constexpr double min = 0.0; + constexpr double max = 1.0; +}; + +template < typename T1, typename T2 > +void transform_sample( + Sample const & in, + Sample & out +) { + out.value = static_cast( in.value * static_cast(Sample::max) ) / Sample::min; +} + + +/* LT IR */ + +@isomorphism +transform_sample + :: Sample ~ <ℝ 0,1> ~ f64 + -> Sample ~ <ℝ 0,1> ~ ℤ_2^256 ~ u8 +transform_sample f = floor( f * 256.0 ) as ℤ_2^256 ~ u8 + +@isomorphism +transform_sample :: Sample ~ <ℝ 0,1> ~ ℤ_2^256 ~ u8 + -> Sample ~ <ℝ 0,1> ~ f64 +transform_sample i = (i as ℝ~f64) / 256.0 + +transform_sample :: Sample~ℝ~T1 -> ℝ~T2 +transform_sample v + + +void main() { + + // read Audio streams + for( unsigned i = 0; i < ) +} + + + + + +/* LT IR */ + +type Color~RGB = { r|red: ℝ_0,1; g|green: ℝ_0,1; b|blue: ℝ_0,1; } +type Color~HSL = { h|hue: ℝ_0,1; s|saturation: ℝ_0,1; l|lightness: ℝ_0,1; } + +validate <ℝ> :: f64 -> {} +validate x = {} + +morph :: Color~RGB -> Color~HSL +morph (r,g,b) = { + let h = .. TODO .. + ... + (h,s,l) +} + +morph :: ℝ_0,1 ~ f64 -> ℝ_0,1 ~ ℤ_256 +morph x = (x * 256.0) % 256 + +morph :: ℝ_0,1 ~ ℤ_256 -> ℝ_0,1 ~ f64 +morph x = (x as f64 / 256.0) + +infix * :: ℝ~f64 -> ℝ~f64 -> ℝ~f64 +infix * a b = f64.mul a b + +clamp :: ℝ -> ℝ -> ℝ -> ℝ +clamp minVal maxVal x = if x < minVal { minVal } + else if x > maxVal { maxVal } + else { x } + +saturate :: ℝ -> Color~HSL -> Color~HSL +saturate f {h,s,l} = { h, clamp(f*s, 0.0, 1.0), l } + +saturate_image :: ℝ -> [Color~HSL] -> [Color~HSL] +saturate_image f pixels = map saturate pixels + +{ + let width : ℕ = 4; + let height : ℕ = 2; + let pixels + : [ + [ + [ Color + ~RGB + ~[ ℝ_0,1 + ~ℤ_256 + ~ + ~[~Char] + ; 3] + ; width] + ~~~[Char] + ; height] + ~~~[Char] + = [ + [000000, 001122, 22ff33, ffe384], + [ff3344, abcdef, ffeebb, 44bb22] + ]; + + pixels = saturate_image 0.3 pixels + + let packed_buf = array_layout_rot + < + [[Color~RGB~[ℝ_0,1; 3]; width]; height], + [[Color; width]; height]; 3] + > + pixels; + +} + + + +brighten_image :: ℕ -> ℕ -> [Color] [[ Color~RGB~[ℝ~f64; 3]; width]; height] ) + + + diff --git a/lt-stdlib/int.lt b/lt-stdlib/int.lt index 45e8344..a31d11c 100644 --- a/lt-stdlib/int.lt +++ b/lt-stdlib/int.lt @@ -16,3 +16,19 @@ export { let int-max = λ{ a:ℤ~machine.Int64; b:ℤ~machine.Int64; } ↦ if( int-gt a b ) { a; } else { b; }; }; + +/* syntax ambiguity */ + +let f'0 = λx:A -> B ↦ { ... }; + +/* could be interpreted as .. */ +let f'1 = λ{x: A -> B} ↦ {}; +/* ..or.. */ +let f'2 = λx:A ↦ B:{}; + + +do { + !a 10; + !b 20; +} + diff --git a/lt-stdlib/string.lt b/lt-stdlib/string.lt new file mode 100644 index 0000000..3e620bc --- /dev/null +++ b/lt-stdlib/string.lt @@ -0,0 +1,41 @@ + +#complexity O(n) +let strlen-nullterm = + λ str : &[Char~Ascii~machine::Word] + ~ & + ~ machine::Address + ~ machine::Word + -> ℤ + ~ ℤ_2^64 + ~ machine::UInt64 + ~ machine::Word +{ + let mut len = 0; + while ( @str ) { + ! len (i+ len 1); + ! str (i+ str 1); + } + len; +}; + +#complexity O(1) +let strlen-lenprefix = + λ str : &[Char~Ascii~machine::Word] + ~ & + ~ &{ + len : ℤ_2^64 + ~ machine::UInt64 + ~ machine::Word, + data : [machine::Word] + } + ~ machine::Address + ~ machine::Word + -> ℤ + ~ ℤ_2^64 + ~ machine::UInt64 + ~ machine::Word +{ + str.len +}; + + diff --git a/lt-stdlib/vec.lt b/lt-stdlib/vec.lt new file mode 100644 index 0000000..e217df7 --- /dev/null +++ b/lt-stdlib/vec.lt @@ -0,0 +1,70 @@ + +type Vec = ΛT ↦ Struct { + len : ℤ_2^64 ~ machine.UInt64 ~ machine.Word ; + capacity : ℤ_2^64 ~ machine.UInt64 ~ machine.Word ; + data : ~ machine.Address ~ machine.UInt64 ~ machine.Word ; +}; + +let yellow:Color~RGB~Vec3i = { + 0; + 220; + 220; +}; + +let fn = λx:ℤ ↦ ℤ:{ + 3; +}; + +let swap = λ{x;y;}:{T;T;} ↦ ℤ:{x;y;} + + let n : ℤ + ~ℤ_2^64 + ~machine.UInt64 + ~machine.Word + = + ℤ + ~ + ~ + ~ Char > + : CF03; + +λ{} -> {x y} : +↦ { + 10; + 5; +} + +let Vec.new = ΛT ↦ λ{} ↦ self:{ + let sizeofT = 1; + !self { + + }; + + !self.len 0; + !self.capacity 10; + !self.data malloc (i* self.capacity sizeofT); +}; + +let Vec.drop = ΛT ↦ λself: ↦ { + mfree self.data; +}; + +let vec-get = + Λ T + ↦ λ vec: + ↦ λ idx: ℤ_2^64 ~ machine.UInt64 ~ machine.Word + ↦ T { + if( int-lt idx vec.len ) { + let j = 0; + let sizeofT = 1; /* todo: */ + + while( int-lt j sizeofT ) { + @ (i+ vec.data + (i+ (i* idx sizeofT) j)); + ! j (i+ j 1); + }; + } else { + print-nullterm 'o''u''t'' ''o''f'' ''b''o''u''n''d''s''\n''\0' + }; + }; + diff --git a/ltcore-intro-examples b/ltcore-intro-examples new file mode 100644 index 0000000..36dc1dd --- /dev/null +++ b/ltcore-intro-examples @@ -0,0 +1,244 @@ +/**~<<~>>~<<~>>~<<~>>~<<~>>~<<~>>~<<~>>~<<~>>~** + * Brief Syntax Definition * + * of the functional language kernel LT-core * + * (please suggest a better name) * + **~<<~>>~<<~>>~<<~>>~<<~>>~<<~>>~<<~>>~<<~>>~** + * (Placeholders are written in CAPS-LOCK) * + **~<<~>>~<<~>>~<<~>>~<<~>>~<<~>>~<<~>>~<<~>>~** + * + * + * Type-Application + * ------------------ + * specializes a generic symbol + * `` + * + * `` + * + * Type-Abstraction + * ------------------ + * creates a generic symbol with a type-variable and optional trait bounds + * `` + * let GENERIC-SYMBOL-NAME = Λ TYPE-ARG-NAME : TYPE-ARG-BOUNDS . VAL-EXPR ; + * `` + * + * Term-Application + * ------------------ + * calculates result from applying arguments to a function + * with prefix-notation and left-associative `(` `)` parens. + * `` + * FUNCTION-NAME ARG-EXPR + * `` + * + * Term-Abstraction + * ------------------ + * binds a function definition to a symbol + * `` + * let SYMBOL-NAME = λ ARG-BINDING -> RESULT-BINDING ↦ RESULT-EXPR ; + * `` + * + * Argument-Binding-Block + * ------------------------ + * binds variable names to function arguments + * `` + * λ { + * ARG-NAME-1 : ARG-TYPE-1 ; + * ARG-NAME-2 : ARG-TYPE-2 ; + * ... ; + * ARG-NAME-N : ARG-TYPE-N ; + * } + * `` + * + * Result-Binding-Block + * ---------------------- + * binds variable names to function result + * `` + * -> { + * RESULT-NAME-1 : RESULT-TYPE-1 ; + * RESULT-NAME-2 : RESULT-TYPE-2 ; + * ... + * RESULT-NAME-N : RESULT-TYPE-N ; + * } + * `` + * + * Construction-Block + * -------------------- + * builds up result value of the function + * by sequentially pushing values to the stack + * `` + * ↦ { + * VAL-EXPR-N ; + * ... + * VAL-EXPR-2 ; + * VAL-EXPR-1 ; + * } + * `` + * + * Symbol visibility + * ------------------- + * Symbols defined through `let` are local + * to the scope of the block they are contained in, + * but can be made visible in the parent block with `export`. + * + * `` + * { + * export { let x = 5; }; + * x; + * } + * `` + * + * Explicit Dataflow + * ------------------- + * write to memory referenced a symbol or expression + * `` + * ! REF-EXPR VAL-EXPR ; + * `` + * where + * - `REF-EXPR` is an expression of type &T + * - `VAL-EXPR` is of type T + * + **~<<~>>~<<~>>>~<<~>>~<<<~>>>~<<~>>~<<<~>>>~<<~>>~<<<~>>~<<~>>** + */ + + +/* Results of a function can be defined either by construction blocks + * or by statement blocks that write variables bound to the result. + * The following function definitions of dup'n|n∈ℕ are equivalent: + */ +let dup'0 = λx ↦ { x; x; }; +let dup'1 = ΛT . λx:T -> { _:T; _:T; } ↦ { x; x; }; +let dup'2 = ΛT . λx:T -> { a:T; b:T; } ↦ { !a x; !b x; }; + +/* note that construction blocks build up a stack, i.e. + * the topmost element / the first element of a structure + * is at the last position (like expressions in postfix). + */ +let swap'0 = ΛT . λ{ x:T; y:T; } ↦ { x; y; }; +let swap'1 = ΛT . λ{ x:T; y:T; } -> { yo:T; xo:T } ↦ { !yo x; !xo y; }; + +/* binding blocks can be curried + */ +let swap'2 = ΛT . λx:T ↦ λy:T ↦ { x; y; }; + +/* Type-Annotations are possible in many places. + * With an annotation of a function-type, the types + * of its argument variables can be deduced. + */ +let swap'3 : { T; T; } -> { T; T; } = ΛT . λ{ x y } ↦ { x; y; }; + +/* + * T.F.A.E.: + */ +let fun'1 : {A, B} -> C = λ{a b} ↦ { ... } ; +let fun'2 : A -> B -> C = λ{a b} ↦ { ... } ; +let fun'3 = λ{a: A; b: B;} ↦ C: { ... }; +let fun'4 = λ{a: A} ↦ λ{b: B} ↦ C: { ... }; + +/* Argument-Bindings with a structure-type will + * result in further (localized) variable bindings + * according to the struct-type definition. + */ +let vec2.magnitude'0 = λ{ x:ℝ; y: ℝ; } ↦ sqrt (+ (* x x) (* y y)) ; +let vec2.magnitude'1 = λa:{ x:ℝ; y:ℝ; } ↦ sqrt (+ (* a.x a.x) (* a.y a.y)) ; + + + +/* And now more advanced stuff... + */ +let Iterator = ΛItem . trait Self { + next : &!Self ->