Compare commits

...
Sign in to create a new pull request.

10 commits

Author SHA1 Message Date
ef819b4711
morphisms: remove 'return 0;' at end since it is now added by default 2025-04-03 16:37:46 +02:00
3f1397735c
improve code generation
- improve usage of FUSE
- implement seq-map for different representations
- fix C-types in morph-function arguments
- collect active types and put typedef into header
- add generate_main() to create stdio-morphism
2025-04-02 23:32:06 +02:00
67cec64dfc
fix codegen for seq-map 2025-04-02 15:01:45 +02:00
98592aa596
fuse results of sub- morphisms in complex morphisms 2025-04-02 14:37:31 +02:00
35b747ea15
fix local src/dst types in complex morphisms 2025-04-02 14:31:47 +02:00
39cba1ee57
improve symbol names in generated c code 2025-04-02 14:11:17 +02:00
583892f10d
wip struct morphisms 2025-04-01 18:23:18 +02:00
d98afc294d
exemplaric platform definitions 2025-03-31 10:29:57 +02:00
bce52e9fcf
replace native.Float/native.Double with native.Float32/native.Float64 2025-03-25 19:38:56 +01:00
21bb33193a
wip struct morphisms 2025-03-24 10:14:25 +01:00
22 changed files with 1222 additions and 575 deletions

View file

@ -3,70 +3,44 @@
```
morph_angle_as_degrees_to_turns_float ()
Angle ~ Degrees ~ ~ native.Float
--> Angle ~ Turns ~ ~ native.Float
```
*dst = *src / 360.0;
return 0;
```
Angle ~ Degrees ~ ~ native.Float32
--> Angle ~ Turns ~ ~ native.Float32
```*dst = *src / 360.0;```
morph_angle_as_degrees_to_turns_double ()
Angle ~ Degrees ~ ~ native.Double
--> Angle ~ Turns ~ ~ native.Double
```
*dst = *src / 360.0;
return 0;
```
Angle ~ Degrees ~ ~ native.Float64
--> Angle ~ Turns ~ ~ native.Float64
```*dst = *src / 360.0;```
morph_angle_as_turns_to_degrees_float ()
Angle ~ Turns ~ ~ native.Float
--> Angle ~ Degrees ~ ~ native.Float
```
*dst = *src * 360.0;
return 0;
```
Angle ~ Turns ~ ~ native.Float32
--> Angle ~ Degrees ~ ~ native.Float32
```*dst = *src * 360.0;```
morph_angle_as_turns_to_degrees_double ()
Angle ~ Turns ~ ~ native.Double
--> Angle ~ Degrees ~ ~ native.Double
```
*dst = *src * 360.0;
return 0;
```
Angle ~ Turns ~ ~ native.Float64
--> Angle ~ Degrees ~ ~ native.Float64
```*dst = *src * 360.0;```
morph_angle_as_radians_to_turns_float ()
Angle ~ Radians ~ ~ native.Float
--> Angle ~ Turns ~ ~ native.Float
```
*dst = *src / PHI;
return 0;
```
Angle ~ Radians ~ ~ native.Float32
--> Angle ~ Turns ~ ~ native.Float32
```*dst = *src / PHI;```
morph_angle_as_radians_to_turns_double ()
Angle ~ Radians ~ ~ native.Double
--> Angle ~ Turns ~ ~ native.Double
```
*dst = *src / PHI;
return 0;
```
Angle ~ Radians ~ ~ native.Float64
--> Angle ~ Turns ~ ~ native.Float64
```*dst = *src / PHI;```
morph_angle_as_turns_to_radians_float ()
Angle ~ Turns ~ ~ native.Float
--> Angle ~ Radians ~ ~ native.Float
```
*dst = *src * PHI;
return 0;
```
Angle ~ Turns ~ ~ native.Float32
--> Angle ~ Radians ~ ~ native.Float32
```*dst = *src * PHI;```
morph_angle_as_degrees_to_radians_double ()
Angle ~ Turns ~ ~ native.Double
--> Angle ~ Radians ~ ~ native.Double
```
*dst = *src * PHI;
return 0;
```
Angle ~ Turns ~ ~ native.Float64
--> Angle ~ Radians ~ ~ native.Float64
```*dst = *src * PHI;```

View file

@ -60,8 +60,6 @@ morph_digit_as_uint8_to_char (Radix:_16)
fprintf(stderr, "digit %u is out of rage for char\n", *dst);
return -1;
}
return 0;
```
morph_digit_as_uint64_to_char (Radix:_16)
@ -76,6 +74,4 @@ morph_digit_as_uint64_to_char (Radix:_16)
fprintf(stderr, "digit %u is out of rage for char\n", *dst);
return -1;
}
return 0;
```

View file

@ -10,8 +10,6 @@ morph_array_as_valterm_to_lenpfx (Terminator:native.UInt8)
length_prefix_uint64_t_array_uint8_t_clear(dst);
while( *src != Terminator )
length_prefix_uint64_t_array_uint8_t_push(dst, *src++);
return 0;
```
@ -23,8 +21,6 @@ morph_array_as_lenpfx_to_valterm (Terminator:native.UInt8)
*dst++ = src->items[i];
*dst = Terminator;
return 0;
```
morph_array_as_lenpfx_to_continuation_bit (T:Type)
@ -42,6 +38,4 @@ morph_array_as_lenpfx_to_continuation_bit (T:Type)
if( i+1 < src->len )
dst[i] |= (1<<(n_bits-1));
}
return 0;
```

View file

@ -11,7 +11,6 @@ morph_nat_as_u64_to_pos ()
```
dst->len = 1;
dst->items[0] = *src;
return 0;
```
morph_nat_as_pos_to_u64 (Endianness:Type)
@ -22,7 +21,6 @@ morph_nat_as_pos_to_u64 (Endianness:Type)
~ native.UInt64
```
*dst = src->items[0];
return 0;
```
morph_posint_radix_le (SrcRadix:, DstRadix:)
@ -52,8 +50,6 @@ morph_posint_radix_le (SrcRadix:, DstRadix:)
value /= DstRadix;
}
#endif
return 0;
```
morph_posint_radix_be (SrcRadix:, DstRadix:)
@ -91,8 +87,6 @@ morph_posint_radix_be (SrcRadix:, DstRadix:)
value /= DstRadix;
}
#endif
return 0;
```
morph_posint_endianness (Radix:)

View file

@ -4,102 +4,87 @@
morph_real_as_decimalstr_to_float ()
~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8>
--> ~ native.Float
```
sscanf(src, "%f", dst);
return 0;
```
--> ~ native.Float32
```sscanf(src, "%f", dst);```
morph_real_as_decimalstr_to_double ()
~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8>
--> ~ native.Double
```
sscanf(src, "%lf", dst);
return 0;
```
--> ~ native.Float64
```sscanf(src, "%lf", dst);```
morph_real_as_float_to_decimalstr ()
~ native.Float
~ native.Float32
--> ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8>
```
sprintf(dst, "%f", *src);
return 0;
```
```sprintf(dst, "%f", *src);```
morph_real_as_double_to_decimalstr ()
~ native.Double
~ native.Float64
--> ~ <PosInt 10 BigEndian> ~ <Seq~<ValueTerminated 0> <Digit 10>~Char~Ascii~native.UInt8>
```
sprintf(dst, "%f", *src);
return 0;
```
```sprintf(dst, "%f", *src);```
morph_real_as_float_to_double ()
~ native.Float
--> ~ native.Double
```
*dst = *src;
return 0;
```
~ native.Float32
--> ~ native.Float64
```*dst = *src;```
morph_real_as_double_to_float ()
~ native.Double
--> ~ native.Float
~ native.Float64
--> ~ native.Float32
```
fprintf(stderr, "Warning: morphin Double -> Float. Precision loss!");
*dst = *src;
return 0;
```
morph_real_as_u64_to_float ()
~ ~ native.UInt64
--> ~ native.Float
--> ~ native.Float32
```
fprintf(stderr, "Warning: morphin UInt64 -> Float. Precision loss!");
*dst = *src;
return 0;
```
morph_real_as_u64_to_double ()
~ ~ native.UInt64
--> ~ native.Double
--> ~ native.Float64
```
fprintf(stderr, "Warning: morphin UInt64 -> Double. Precision loss!");
*dst = *src;
return 0;
```
morph_real_as_nat_to_quantized_linear ()
~ ~ native.UInt64
--> ~ <QuantizedLinear 0 1 1> ~ ~ native.UInt64
```
*dst = *src;
```
morph_real_as_quantized_linear_to_float (Begin: , End: , Steps: )
~ <QuantizedLinear Begin End Steps> ~ ~ native.UInt64
--> ~ native.Float
--> ~ native.Float32
```
*dst = (float)Begin + ( *src * ((float)End - (float)Begin) ) / (float)Steps;
return 0;
```
morph_real_as_float_to_quantized_linear (Begin: , End: , Steps: )
~ native.Float
~ native.Float32
--> ~ <QuantizedLinear Begin End Steps> ~ ~ native.UInt64
```
*dst = ((*src - (float)Begin) * (float)Steps) / ((float)End - (float)Begin);
return 0;
```
morph_real_as_quantized_linear_to_double (Begin: , End: , Steps: )
~ <QuantizedLinear Begin End Steps> ~ ~ native.UInt64
--> ~ native.Double
--> ~ native.Float64
```
*dst = (double)Begin + ( *src * ((double)End - (double)Begin) ) / (double)Steps;
return 0;
```
morph_real_as_double_to_quantized_linear (Begin: , End: , Steps: )
~ native.Double
~ native.Float64
--> ~ <QuantizedLinear Begin End Steps> ~ ~ native.UInt64
```
*dst = ((*src - (double)Begin) * (double)Steps) / ((double)End - (double)Begin);
return 0;
```

View file

@ -2,33 +2,21 @@
```
morph_celsius_to_kelvin ()
Temperature ~ Celsius ~ ~ native.Float
--> Temperature ~ Kelvin ~ ~ native.Float
```
*dst = *src + 273.15;
return 0;
```
Temperature ~ Celsius ~ ~ native.Float32
--> Temperature ~ Kelvin ~ ~ native.Float32
```*dst = *src + 273.15;```
morph_kelvin_to_celsius ()
Temperature ~ Kelvin ~ ~ native.Float
--> Temperature ~ Celsius ~ ~ native.Float
```
*dst = *src - 273.15;
return 0;
```
Temperature ~ Kelvin ~ ~ native.Float32
--> Temperature ~ Celsius ~ ~ native.Float32
```*dst = *src - 273.15;```
morph_celsius_to_fahrenheit ()
Temperature ~ Celsius ~ ~ native.Float
--> Temperature ~ Fahrenheit ~ ~ native.Float
```
*dst = (*src * 9.0 / 5.0) + 32.0;
return 0;
```
Temperature ~ Celsius ~ ~ native.Float32
--> Temperature ~ Fahrenheit ~ ~ native.Float32
```*dst = (*src * 9.0 / 5.0) + 32.0;```
morph_fahrenheit_to_celsius ()
Temperature ~ Fahrenheit ~ ~ native.Float
--> Temperature ~ Celsius ~ ~ native.Float
```
*dst = (*src - 32.0) * 5.0 / 9.0;
return 0;
```
Temperature ~ Fahrenheit ~ ~ native.Float32
--> Temperature ~ Celsius ~ ~ native.Float32
```*dst = (*src - 32.0) * 5.0 / 9.0;```

View file

@ -11,5 +11,4 @@ morph_unixtime_to_iso ()
if (!timeinfo) return -1;
strftime((char*)dst, 20, "%Y-%m-%dT%H:%M:%SZ", timeinfo);
return 0;
```

View file

@ -0,0 +1,17 @@
```
```
morph_nat_as_u8_to_u16 ()
~ native.UInt8
--> ~ native.UInt16
```*dst = *src;```
morph_nat_as_u16_to_u32 ()
~ native.UInt16
--> ~ native.UInt32
```*dst = *src;```
morph_nat_as_u32_to_u64 ()
~ native.UInt32
--> ~ native.UInt64
```*dst = *src;```

View file

@ -28,7 +28,6 @@ morph_string_as_utf8_to_ascii ()
}
}
*dst = 0;
return 0;
```
morph_string_as_ascii_to_utf32 ()
@ -39,7 +38,6 @@ morph_string_as_ascii_to_utf32 ()
```
while( *src ) { *dst++ = *src++; }
*dst = 0;
return 0;
```
morph_string_as_utf8_to_utf32 ()
@ -89,6 +87,4 @@ morph_string_as_utf8_to_utf32 ()
*dst++ = val;
*dst++ = 0;
return 0;
```

View file

@ -27,8 +27,6 @@ morph_seqseq_valsep_uint8 (T: Type, SrcDelim: T, DstDelim: T)
length_prefix_uint64_t_array_uint8_t_push( dst, src->items[i] );
}
}
return 0;
```
@ -66,8 +64,6 @@ morph_seqseq_as_valsep_to_lenpfx (T: Type, Delim: T, EscKey: T)
cur++;
}
}
return 0;
```
morph_seqeq_as_lenpfx_to_valsep (T: Type, Delim: T, EscKey: T)
@ -94,6 +90,4 @@ morph_seqeq_as_lenpfx_to_valsep (T: Type, Delim: T, EscKey: T)
length_prefix_uint64_t_array_uint8_t_push( Delim );
}
}
return 0;
```

View file

@ -10,8 +10,6 @@ morph_i64_as_twos_complement_to_zigzag ()
} else {
*dst = (2 * (uint64_t)(- *src)) - 1;
}
return 0;
```
morph_i64_as_zigzag_to_twos_complement ()

100
platforms/json.lt Normal file
View file

@ -0,0 +1,100 @@
type UTF8-String = <Seq Char~Unicode> ~ UTF-8 ~ <Seq~<ValueTerminated 0> native.UInt8> ;
type SerializedJson.Value = json.Value
~ <Enum
<Null json.Null ~ SerializedJson.Null >
<String json.String ~ SerializedJson.String >
<Number json.Number ~ SerializedJson.Number >
<Bool json.Bool ~ SerializedJson.Bool >
<Array json.Array ~ SerializedJson.Array >
<Object json.Object ~ SerializedJson.Object >>
~ <Seq Char> ;
type SerializedJson.Null = < Struct~<Seq Char> "\"null\"" > ;
type SerializedJson.String = <Seq Char>
~ <Struct~<Seq Char> "\"" <Seq Char> "\"">
~ <Seq Char> ;
type SerializedJson.Number =
~ <PosInt 10 BigEndian>
~ <Seq <Digit 10> ~ Char> ;
type SerializedJson.Bool = Bool
~ <Enum~<Seq Char>
<True~"\"true\"" <>>
<False~"\"false\"" <>>>
~ <Seq Char> ;
type SerializedJson.Array = <Struct~<Seq Char>
"["
<Seq json.Value>
~ <ValueSep ',' Char>
~ <Seq Char>
"]" >
~ <Seq Char> ;
type SerializedJson.Object = <Struct~<Seq Char>
"{"
<members <Seq
<Struct~<Seq Char>
<key json.String>
":"
<value json.Value>>>>
"}"
>
~ <Seq Char>;
type parsedJson.Value = json.Value ~ <Enum~native.UInt8
< parsedJson_Null~0 <> >
< parsedJson_String~1 <Ref UTF8-String> ~ native.Address >
< parsedJson_Int~2 ~~native.UInt64 >
< parsedJson_Float~2 ~native.Float64 >
< parsedJson_Bool~3 Bool ~ native.UInt8 >
< parsedJson_Array~4 <Ref <Seq ~ <LengthPrefix native.UInt64>
parsedJsonValue
>
>
~ native.Address >
< parsedJson_Object~5 <Ref <Seq ~ <LengthPrefix native.UInt64>
<Struct
<key <Ref UTF8-String> ~ native.Address>
<val parsedJsonValue>
>
>
~ native.Address >>
~ <Struct
<tag native.UInt8>
native.UInt64 >;
parse_json_value ()
json.Value ~ UTF8-String
--> json.Value ~ parsedJsonValue
```
{
dst->tag = PARSED_JSON_NULL;
dst->parsedJson_Null;
}
{
dst->tag = PARSED_JSON_STRING;
dst->parsedJson_String = malloc(len);
strncpy(dst->parsedJson_String, src, len);
src += len;
}
{
dst->tag = PARSED_JSON_NUMBER;
MORPH(
" ~ ~ <PosInt 10 BigEndian> ~ <Seq <Digit 10> ~ Char> ~ UTF8-String",
" ~ ~ native.UInt64",
src,
&dst->parsedJson_Number
);
}
```

0
platforms/json5.lt Normal file
View file

3
platforms/protobuf.lt Normal file
View file

@ -0,0 +1,3 @@
type protobuf.Varint = ~ <PosInt 128 LittleEndian> ~ <Seq~MsbCont <Digit 128> ~ _128 ~ native.UInt8> ;
type protobuf.String = <Seq Char ~ Unicode> ~ UTF-8 ~ <Seq ~ <LengthPrefix protobuf.Varint> Byte> ;

0
platforms/spapod.lt Normal file
View file

5
platforms/x86.lt Normal file
View file

@ -0,0 +1,5 @@
type x86.UInt64 = _2/\64 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 8> <Digit 256> ~ x86.UInt8 >;
type x86.UInt32 = _2/\32 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 4> <Digit 256> ~ x86.UInt8 >;
type x86.UInt16 = _2^16 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 2> <Digit 256> ~ x86.UInt8 >;
type x86.UInt8 = _256 ~ <Posint 2 BigEndian> ~ <Seq~<StaticLength 8> <Digit 2> ~ Bit>;

View file

@ -1,419 +1,402 @@
use {
laddertypes::{TypeDict, TypeTerm, parser::*, unparser::*, morphism::{Morphism, MorphismInstance}},
crate::morphism::{LdmcPrimCMorphism, LdmcMorphism}
crate::{c_gen_types::{encode_morph_type_to_symbol, encode_type_to_arg_ty, encode_type_to_symbol, encode_type_to_value, get_c_repr_type}, morphism::LdmcPrimMorph, struct_layout::{get_type_size, LayoutType, ObjectSize, StructLayout}}, chumsky::{chain::Chain, primitive::Container}, laddertypes::{morphism::{Morphism, MorphismInstance}, morphism_sugared::{MorphismInstance2, SugaredMorphism, SugaredMorphismType}, parser::*, substitution_sugared::SugaredSubstitution, unparser::*, Substitution, SugaredEnumVariant, SugaredStructMember, SugaredTypeTerm, TypeDict, TypeTerm}, std::collections::HashMap
};
/*
*/
pub fn get_c_repr_kind(kind: String) -> Option<String> {
match kind.as_str() {
"" => Some("uint64_t".into()),
_ => None
}
}
/* for a given ladder type `t`, get the corresponding C type
*/
pub fn get_c_repr_type(dict: &mut impl TypeDict, t: laddertypes::TypeTerm, skip_pointer: bool) -> Option<String> {
let lnf = t.normalize().decurry().get_lnf_vec();
match lnf.last() {
Some(t) => {
if t == &dict.parse("Byte").expect("parse")
|| t == &dict.parse("native.UInt8").expect("parse")
|| t == &dict.parse("<StaticLength 8 Bit>").expect("parse")
{
Some("uint8_t".into())
} else if t == &dict.parse("native.UInt16").expect("parse") {
Some("uint16_t".into())
} else if t == &dict.parse("native.UInt32").expect("parse") {
Some("uint32_t".into())
} else if t == &dict.parse("native.UInt64").expect("parse") {
Some("uint64_t".into())
} else if t == &dict.parse("native.Float").expect("parse") {
Some("float".into())
} else if t == &dict.parse("native.Double").expect("parse") {
Some("double".into())
} else {
match t {
laddertypes::TypeTerm::App(args) => {
if args[0] == laddertypes::TypeTerm::TypeID(dict.get_typeid(&"LengthPrefix".into()).unwrap())
{
let length_c_type : String = get_c_repr_type(dict, args[1].clone(), false)?;
let item_c_type : String = get_c_repr_type(dict, args[2].clone(), false)?;
match length_c_type.as_str() {
"uint8_t" |
"uint16_t" |
"uint32_t" |
"uint64_t" => {}
_ => {
eprintln!("invalid length type!");
return None;
}
}
match item_c_type.as_str() {
"uint8_t" |
"uint16_t" |
"uint32_t" |
"uint64_t" => {}
_ => {
eprintln!("invalid item type!");
return None;
}
}
Some(format!("LengthPrefix_{}_Array_{}", length_c_type, item_c_type))
}
else if args[0] == laddertypes::TypeTerm::TypeID(dict.get_typeid(&"ValueTerminated".into()).unwrap())
{
let _delim_val = args[1].clone();
let c_type = get_c_repr_type(dict, args[2].clone(), false)?;
if skip_pointer {
Some(c_type)
} else {
Some(format!("{} *", c_type))
}
}
else if args[0] == laddertypes::TypeTerm::TypeID(dict.get_typeid(&"MsbCont".into()).unwrap())
{
let c_type = get_c_repr_type(dict, args[1].clone(), false)?;
if skip_pointer {
Some(c_type)
} else {
Some(format!("{} *", c_type))
}
}
else {
None
}
}
_ => None
}
}
}
None => None
}
}
pub fn encode_type_to_symbol(dict: &mut impl TypeDict, t: &laddertypes::TypeTerm)-> String {
match t {
laddertypes::TypeTerm::Char(c) => {
match c {
'.' => format!("_dot_"),
_ =>
format!("{}", (*c as u64))
}
},
laddertypes::TypeTerm::Num(n) => {
format!("{}", n)
}
laddertypes::TypeTerm::TypeID(ty_id) => {
if let Some(name) = dict.get_typename(ty_id) {
format!("{}", name.replace(".", "_dot_"))
} else {
format!("")
}
}
laddertypes::TypeTerm::Ladder(rs) |
laddertypes::TypeTerm::App(rs) => {
let mut s = String::new();
for r in rs {
s.push('_');
s.push_str(&encode_type_to_symbol(dict, r));
}
s
}
}
}
pub fn encode_type_to_value(dict: &mut impl TypeDict, t: &laddertypes::TypeTerm) -> String {
dict.unparse(t)
}
pub fn generate_main(type_dict: &mut impl TypeDict, path: Vec<MorphismInstance<LdmcMorphism>>, src_type: TypeTerm, dst_type: TypeTerm) {
let mut i = 0;
/* todo: collect include files from morphism base */
println!(r#"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
"#);
let mut existing_instantiations = Vec::new();
for morph_inst in path.iter() {
match &morph_inst.m {
LdmcMorphism::Primitive( item_morph ) => {
let name = item_morph.instantiated_symbol_name(type_dict, &morph_inst.σ);
if ! existing_instantiations.contains(&name) {
if let Some(s) = item_morph.generate_instantiation(type_dict, &morph_inst.σ) {
println!("{}", s);
} else {
eprintln!("couldnt generate instance {}", name);
}
existing_instantiations.push( name );
}
}
LdmcMorphism::LengthPrefixMap { length_prefix_type, item_morph } => {
let name = item_morph.instantiated_symbol_name(type_dict, &morph_inst.σ);
if ! existing_instantiations.contains(&name) {
if let Some(s) = item_morph.generate_instantiation(type_dict, &morph_inst.σ) {
println!("{}", s);
} else {
eprintln!("couldnt generate instance {}", name);
}
existing_instantiations.push( name );
}
}
_ => {}
}
}
println!(r#"
int main() {{
uint8_t bufA[128];
uint8_t bufB[128];
memset(bufA, 0, sizeof(bufA));
memset(bufB, 0, sizeof(bufB));
char in_str[] = "read :: {} \n";
char out_str[]= "write:: {} \n";
write(2, in_str, strlen(in_str));
write(2, out_str, strlen(out_str));
int l = read(0, bufA, sizeof(bufA));
//fprintf(stderr, "read %d bytes\n", l);
"#,
type_dict.unparse(&src_type).replace("\\", "\\\\"),
type_dict.unparse(&dst_type).replace("\\", "\\\\") );
for morph_inst in path.iter() {
println!(r#"
/* morph to {}
...with
morph {}
---> {},
subst σ = {:?},
halo Ψ = {}
*/"#,
type_dict.unparse(&morph_inst.get_type().dst_type.param_normalize().decurry()),
type_dict.unparse(&morph_inst.m.get_type().src_type),
type_dict.unparse(&morph_inst.m.get_type().dst_type),
morph_inst.σ,
type_dict.unparse(&morph_inst.halo),
);
morph_inst.m.generate_call(type_dict, &morph_inst.σ, i);
i += 1;
}
let out_buf = if i%2==0 { "bufA" } else { "bufB" };
let is_string = false;
if let Ok((halo, σ)) = laddertypes::subtype_unify(
&dst_type,
&type_dict.parse("<Seq~<ValueTerminated 0> native.UInt8>").unwrap()
) {
println!(r#"
printf("%s\n", {});"#, out_buf);
} else if let Ok((halo, σ)) = laddertypes::subtype_unify(
&dst_type,
&type_dict.parse("<Seq~<LengthPrefix native.UInt64> native.UInt8>").unwrap()
) {
println!(r#"
/* write output
*/
{{
LengthPrefix_uint64_t_Array_uint8_t * buf = (void*){};
write(1, {}, sizeof(uint64_t) + buf->len);
}}"#, out_buf, out_buf);
} else {
println!(r#"
write(1, {}, sizeof({}));"#,
out_buf,
out_buf
);
}
println!(r#"
return 0;
}}
"#);
eprintln!("Success: generated C code");
}
impl LdmcPrimCMorphism {
pub fn instantiated_symbol_name(&self, dict: &mut impl TypeDict,
σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::TypeTerm>) -> String {
impl LdmcPrimMorph {
pub fn instantiated_symbol_name(&self, dict: &mut impl TypeDict, σ: &impl SugaredSubstitution) -> String {
let mut s = self.symbol.clone();
for (k_id,v) in self.type_args.iter() {
if let Some(val_trm) = σ.get(k_id) {
if let laddertypes::TypeID::Var(var_id) = k_id {
let name = dict.get_varname(*var_id).unwrap();
let val_str = encode_type_to_symbol(dict, val_trm);
s.push_str(&format!("_{}_{}", name, val_str));
if let Some(val_trm) = σ.get(k_id) {
if let laddertypes::TypeID::Var(var_id) = k_id {
//if self.get_type().strip_halo().src_type.contains_var(*var_id) ||
//self.get_type().strip_halo().dst_type.contains_var(*var_id) {
let name = dict.get_varname(*var_id).unwrap();
let val_str = encode_type_to_symbol(dict, &val_trm);
s.push_str(&format!("_{}_{}", name, val_str));
//}
}
} else {
if let laddertypes::TypeID::Var(var_id) = k_id {
let k = dict.get_varname(*var_id).unwrap();
s.push_str(&format!("_{:?}_MISSING", k));
eprintln!("INCOMPLETE MORPHISM INSTANTIATION, missing type parameter {} ({})", k, var_id);
}
}
} else {
if let laddertypes::TypeID::Var(var_id) = k_id {
let k = dict.get_varname(*var_id).unwrap();
s.push_str(&format!("_{:?}_MISSING", k));
eprintln!("INCOMPLETE MORPHISM INSTANTIATION, missing {} ({})", k, var_id);
}
}
}
s
}
pub fn expected_c_type_signature(&self, dict: &mut impl TypeDict,
σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::TypeTerm>) -> String {
σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::SugaredTypeTerm>
) -> String {
format!("int {} ({} const * restrict src, {} * restrict dst);",
self.instantiated_symbol_name(dict, σ),
get_c_repr_type(dict, self.src_type.clone(), true).expect("cant get c-repr type for src type"),
get_c_repr_type(dict, self.dst_type.clone(), true).expect("cant get c-repr type for dst type"))
get_c_repr_type(dict, self.ty.src_type.clone(), true).expect("cant get c-repr type for src type"),
get_c_repr_type(dict, self.ty.dst_type.clone(), true).expect("cant get c-repr type for dst type"))
}
pub fn generate_instantiation(&self, dict: &mut impl TypeDict, σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::TypeTerm>) -> Option<String> {
pub fn generate_instantiation(&self, dict: &mut impl TypeDict, σ: &impl SugaredSubstitution) -> Option<String> {
let mut s = String::new();
let symbol = self.instantiated_symbol_name(dict, σ);
let src_c_symbol = encode_type_to_arg_ty(dict, &self.ty.strip_halo().src_type.clone().apply_subst(σ).get_floor_type().1);
let dst_c_symbol = encode_type_to_arg_ty(dict, &self.ty.strip_halo().dst_type.clone().apply_subst(σ).get_floor_type().1);
s.push_str(&format!(r#"
int {} ( {} const * restrict src, {} * restrict dst ) {{
"#,
self.instantiated_symbol_name(dict, &σ),
get_c_repr_type(dict, self.src_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone(), true).expect("cant get c-repr-type"),
get_c_repr_type(dict, self.dst_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone(), true).expect("cant get c-repr-type"),
symbol, src_c_symbol, dst_c_symbol,
));
for (ty_id, kind) in self.type_args.iter() {
if let Some(val) = σ.get(ty_id) {
eprintln!("val = {}", dict.unparse(&val));
let type_var_value =
if let Some(c_repr_type) = get_c_repr_type(dict, val.clone(), true) {
c_repr_type
} else {
encode_type_to_value(dict, val)
};
s.push_str(&format!(" #define {} {}\n", dict.get_typename(&ty_id).unwrap(), type_var_value));
}
}
s.push_str(&self.c_source);
for (ty_id, kind) in self.type_args.iter() {
s.push_str(&format!("\n #undef {}", dict.get_typename(&ty_id).unwrap()));
}
s.push_str(&format!(r#"
return 0;
}}
"#));
Some(s)
}
}
impl LdmcMorphism {
pub fn generate_call(&self, dict: &mut impl TypeDict, σ: &std::collections::HashMap<laddertypes::TypeID, laddertypes::TypeTerm>, i: u64) {
match self {
LdmcMorphism::Primitive(prim_morph) => {
let src_c_type = get_c_repr_type(dict, prim_morph.src_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone(), true).expect("cant get c-repr type for src type");
let dst_c_type = get_c_repr_type(dict, prim_morph.dst_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone(), true).expect("cant get c-repr type for dst type");
let src_buf = if i%2 == 0 { "bufA" } else { "bufB" };
let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" };
println!(r#"
{}
{} const * restrict src = (void*) {};
{} * restrict dst = (void*) {};
{} ( src, dst );
{}"#,
'{',
src_c_type, src_buf,
dst_c_type, dst_buf,
prim_morph.instantiated_symbol_name(dict, σ),
'}');
pub struct LdmcCTargetMorph {
includes: Vec< String >,
active_types: Vec< SugaredTypeTerm >,
active_instantiations: Vec< LdmcPrimMorph >,
}
impl LdmcCTargetMorph {
pub fn new() -> Self {
LdmcCTargetMorph {
includes: vec![
"#include <stdint.h>".into(),
"#define FUSE(morph, src, dst) { int result = morph(src,dst); if(result) return result; }".into(),
],
active_instantiations: Vec::new(),
active_types: Vec::new(),
}
}
pub fn add_type(&mut self, ty: SugaredTypeTerm) {
if ! self.active_types.contains(&ty) {
match &ty {
SugaredTypeTerm::Seq { seq_repr, items } =>{
self.add_type(items.first().unwrap().clone());
}
_=>{}
}
LdmcMorphism::LengthPrefixMap { length_prefix_type, item_morph } => {
let src_type = self.get_type().src_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone();
let dst_type = self.get_type().dst_type.clone().apply_substitution(&|k| σ.get(k).cloned()).clone();
self.active_types.push(ty.clone());
}
}
eprintln!("length prefix type ={:?}", length_prefix_type);
eprintln!("src_type ={:?}", src_type);
eprintln!("dst_type = {:?}", dst_type);
pub fn add_instantiation(
&mut self,
dict: &mut impl TypeDict,
morph: MorphismInstance2<LdmcPrimMorph>,
) -> Result<LdmcPrimMorph, ()> {
let new_inst = self.bake_morphism(dict, morph)?;
if ! self.active_instantiations.contains(&new_inst) {
self.active_instantiations.push(new_inst.clone());
}
dict.add_varname("S".into());
let ty = new_inst.get_type().strip_halo();
self.add_type(ty.src_type.get_floor_type().1);
self.add_type(ty.dst_type.get_floor_type().1);
let γ_src = laddertypes::unify(
&dict.parse("<Seq~<LengthPrefix S> T>").expect("parse template"),
&src_type
).expect("cant get src item type");
Ok(new_inst)
}
let γ_dst = laddertypes::unify(
&dict.parse("<Seq~<LengthPrefix S> T>").expect("parse template"),
&dst_type
).expect("cant get dst item type");
pub fn into_c_source(self, dict: &mut impl TypeDict) -> String {
let mut source = String::new();
for inc in self.includes {
source.push_str(&inc);
source.push('\n');
}
let src_length_type = γ_src.get(&dict.get_typeid(&"S".into()).unwrap()).expect("cant get src-length type").clone();
let dst_length_type = γ_src.get(&dict.get_typeid(&"S".into()).unwrap()).expect("cant get dst-length type").clone();
for ty in self.active_types {
source.push_str(&format!("
typedef {} {};
",
get_c_repr_type(dict, ty.clone(), false).expect(&format!("cant get c-repr type for type '{}'", ty.pretty(dict,0))),
encode_type_to_symbol(dict, &ty)));
}
let length_type = src_length_type;
for m in self.active_instantiations {
source.push_str(&m.generate_instantiation(dict, &HashMap::new()).expect("cant create function"));
}
let src_item_type = γ_src.get(&dict.get_typeid(&"T".into()).unwrap()).expect("cant get src-item type").clone();
let dst_item_type = γ_dst.get(&dict.get_typeid(&"T".into()).unwrap()).expect("cant get src-item type").clone();
source
}
let length_c_type = get_c_repr_type(dict, length_type, true).expect("cant c-repr type for array length");
let src_item_c_type = get_c_repr_type(dict, src_item_type, true).expect("cant c-repr type for src item");
let dst_item_c_type = get_c_repr_type(dict, dst_item_type, true).expect("cant c-repr type for dst item");
let src_c_type = get_c_repr_type(dict, src_type, true).expect("cant get c-repr type for src type");
let dst_c_type = get_c_repr_type(dict, dst_type, true).expect("cant get c-repr type for dst type");
pub fn bake_morphism(
&mut self,
dict: &mut impl laddertypes::TypeDict,
morph_inst: MorphismInstance2<LdmcPrimMorph>,
) -> Result<LdmcPrimMorph, ()> {
eprintln!("bake morphism: {}
------> {}", morph_inst.get_haloless_type().src_type.pretty(dict,0), morph_inst.get_haloless_type().dst_type.pretty(dict, 0));
let map_fn = format!("length_prefix_{}_array_map_{}_to_{}",
length_c_type, src_item_c_type, dst_item_c_type
);
match &morph_inst {
MorphismInstance2::Primitive { ψ, σ, morph } => {
let mut c_source = String::new();
for (ty_id, kind) in morph.type_args.iter() {
if let laddertypes::TypeID::Var(var_id) = ty_id {
//if morph_inst.get_type().strip_halo().src_type.contains_var(*var_id) ||
//morph_inst.get_type().strip_halo().dst_type.contains_var(*var_id) {
if let Some(val) = σ.get(ty_id) {
let type_var_value =
if let Some(c_repr_type) = get_c_repr_type(dict, val.clone(), true) {
c_repr_type
} else {
encode_type_to_value(dict, &val)
};
let src_buf = if i%2 == 0 { "bufA" } else { "bufB" };
let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" };
println!(r#"
{}
{} const * restrict src = (void*) {};
{} * restrict dst = (void*) {};
{} ( {}, src, dst );
{}"#,
'{',
src_c_type, src_buf,
dst_c_type, dst_buf,
map_fn,
item_morph.instantiated_symbol_name(dict, σ),
'}');
c_source.push_str(&format!(" #define {} {}\n", dict.get_typename(&ty_id).unwrap(), type_var_value));
}
//}
}
}
c_source.push_str(&morph.c_source);
for (ty_id, kind) in morph.type_args.iter() {
if let laddertypes::TypeID::Var(var_id) = ty_id {
//if morph_inst.get_type().strip_halo().src_type.contains_var(*var_id) ||
//morph_inst.get_type().strip_halo().dst_type.contains_var(*var_id) {
c_source.push_str(&format!("\n #undef {}", dict.get_typename(&ty_id).unwrap()));
//}
}
}
Ok(LdmcPrimMorph{
symbol: morph.instantiated_symbol_name(dict, σ),
type_args: Vec::new(),
ty: morph_inst.get_type().apply_subst(σ).strip_halo(),
c_source
})
},
MorphismInstance2::Chain { path } => {
let ty = morph_inst.get_type().strip_halo();
let symbol = encode_morph_type_to_symbol(dict, &ty);
let mut c_source = String::new();
if path.len() > 1 {
c_source.push_str(r#"
uint8_t bufA[4096];
uint8_t bufB[4096];
"#);
}
for (i,morph) in path.iter().enumerate() {
if let Ok(inst) = self.add_instantiation(dict, morph.clone()) {
let morph_symbol = inst.instantiated_symbol_name(dict, &morph.get_subst());
let src_buf = if i == 0 { "src" } else if i%2 == 0 { "(void*)bufA" } else { "(void*)bufB" };
let dst_buf = if i+1 == path.len() { "dst" } else if i%2 == 0 { "(void*)bufB" } else { "(void*)bufA" };
c_source.push_str(&format!(r#"
FUSE( {}, {}, {} );"#,
morph_symbol, src_buf, dst_buf,
));
} else {
c_source.push_str(&format!("/* ERROR: missing morphism */"));
eprintln!("failed to add instantiation of item morphism");
}
}
Ok(LdmcPrimMorph {
symbol, type_args: Vec::new(), ty,
c_source
})
}
LdmcMorphism::ValueDelimMap { delim, item_morph } => {
let src_c_type = get_c_repr_type(dict, item_morph.src_type.clone(), false).expect("cant get c-repr type for src type");
let dst_c_type = get_c_repr_type(dict, item_morph.dst_type.clone(), false).expect("cant get c-repr type for dst type");
MorphismInstance2::MapSeq { ψ, seq_repr, item_morph } => {
if let Ok(item_morph_inst) = self.add_instantiation(dict, item_morph.as_ref().clone()) {
if let Some(seq_repr) = seq_repr {
dict.add_varname("Length".into());
dict.add_varname("LengthType".into());
dict.add_varname("TerminatorValue".into());
let src_buf = if i%2 == 0 { "bufA" } else { "bufB" };
let dst_buf = if i%2 == 0 { "bufB" } else { "bufA" };
println!(r#"
{}
{} const * restrict src = (void*) {};
{} * restrict dst = (void*) {};
value_delim_array_map_8_to_64( {}, src, dst );
{}"#,
'{',
src_c_type, src_buf,
dst_c_type, dst_buf,
item_morph.instantiated_symbol_name(dict, σ),
'}');
if let Ok(γ) = laddertypes::unification_sugared::unify(
&dict.parse("<StaticLength Length>").expect("parse type template").sugar(dict),
seq_repr.as_ref()
) {
let length = γ.get(&dict.get_typeid(&"Length".into()).expect("")).expect("cant get Length");
match length {
SugaredTypeTerm::Num(l) => {
let ty = morph_inst.get_type().strip_halo();
let symbol = encode_morph_type_to_symbol(dict, &morph_inst.get_type());
let item_morph_symbol = item_morph_inst.instantiated_symbol_name(dict, &HashMap::new());
self.add_type( morph_inst.get_type().strip_halo().src_type );
self.add_type( morph_inst.get_type().strip_halo().dst_type );
let c_source = format!(r#"
for( size_t i = 0; i < {}; ++i ) {{
FUSE( {}, &src[i], &dst[i] );
}}
"#,
l,
item_morph_symbol,
);
Ok(LdmcPrimMorph{
symbol, type_args: Vec::new(), ty,
c_source
})
}
_ => {
eprintln!("invalid length '{}'", length.pretty(dict, 0));
Err(())
}
}
}
else if let Ok(γ) = laddertypes::unification_sugared::unify(
&dict.parse("<LengthPrefix LengthType>").expect("parse type template").sugar(dict),
seq_repr.as_ref()
) {
// todo: assert that length type is native.UIntX
//let length_type = γ.get(&dict.get_typeid(&"LengthType".into()).expect("")).expect("cant get LengthType");
let ty = morph_inst.get_type().strip_halo();
let symbol = encode_morph_type_to_symbol(dict, &morph_inst.get_type());
let item_morph_symbol = item_morph_inst.instantiated_symbol_name(dict, &HashMap::new());
self.add_type( morph_inst.get_type().strip_halo().src_type );
self.add_type( morph_inst.get_type().strip_halo().dst_type );
let c_source = format!(r#"
for( size_t i = 0; i < src->len; ++i ) {{
FUSE( {}, &src->items[i], &dst->items[i] );
}}
dst->len = src->len;
"#,
item_morph_symbol,
);
Ok(LdmcPrimMorph{
symbol, type_args: Vec::new(), ty,
c_source
})
}
else if let Ok(γ) = laddertypes::unification_sugared::unify(
&dict.parse("<ValueTerminated TerminatorValue>").expect("parse type template").sugar(dict),
seq_repr.as_ref()
) {
let terminator_value = γ.get(&dict.get_typeid(&"TerminatorValue".into()).expect("")).expect("cant get TerminatorValue");
let ty = morph_inst.get_type().strip_halo();
let symbol = encode_morph_type_to_symbol(dict, &morph_inst.get_haloless_type());
let item_morph_symbol = item_morph_inst.instantiated_symbol_name(dict, &HashMap::new());
let terminator = encode_type_to_value(dict, terminator_value);
let c_source = format!(r#"
while( *src != {} ) {{
FUSE( {}, src, dst );
++src;
++dst;
}}
*dst = {};"#,
terminator,
item_morph_symbol,
terminator
);
Ok(LdmcPrimMorph{
symbol, type_args: Vec::new(), ty,
c_source
})
}
else {
eprintln!("Error: Unknown Seq- Representation!!");
Err(())
}
} else {
eprintln!("Error: missing Seq- Representation!!");
Err(())
}
} else {
eprintln!("failed to add item-morph instantiation");
Err(())
}
},
MorphismInstance2::MapStruct { ψ, struct_repr, member_morph } => {
let ty = morph_inst.get_type().strip_halo();
let symbol =encode_morph_type_to_symbol(dict, &morph_inst.get_haloless_type());
let mut c_source = String::new();
for (name, morph) in member_morph.iter() {
if let Ok(inst) = self.add_instantiation(dict, morph.clone()) {
let name = name.replace("-", "_").replace(".","_dot_");
c_source.push_str(
&format!("
FUSE( {}, &src->{}, &dst->{} );
",
inst.symbol,
name, name
));
} else {
c_source.push_str(&format!("/* ERROR: missing morphism for struct member '{}' */", name));
eprintln!("failed to create morphism instantiation for struct member");
return Err(());
}
}
Ok(LdmcPrimMorph{
symbol, type_args: Vec::new(), ty,
c_source
})
}
MorphismInstance2::MapEnum { ψ, enum_repr, variant_morph } => {
todo!();
}
}
}
}
pub fn generate_main(dict: &mut impl TypeDict, morph: MorphismInstance2<LdmcPrimMorph>) -> Result<String, ()> {
let mut target = LdmcCTargetMorph::new();
let ty = morph.get_type();
if let Ok(inst) = target.add_instantiation(dict, morph) {
let mut c_source = target.into_c_source(dict);
c_source.push_str(&format!(r#"
#include <unistd.h>
int main() {{
uint8_t bufIn[4096];
uint8_t bufOut[4096];"#));
let (src_top, src_floor) = ty.src_type.get_floor_type();
if src_floor == dict.parse("<Seq~<ValueTerminated 0> native.UInt8>").expect("").sugar(dict) {
c_source.push_str("scanf(\"%s\", bufIn);");
} else {
c_source.push_str("read(0, bufIn, sizeof(bufIn));");
}
c_source.push_str(&format!(r#"FUSE( {}, (void const*)bufIn, (void*)bufOut );"#, inst.instantiated_symbol_name(dict, &HashMap::new())));
if let Ok(ψ) = laddertypes::unification_sugared::subtype_unify(
&ty.src_type,
&dict.parse("<Seq~<ValueTerminated 0> native.UInt8>").expect("").sugar(dict)
) {
c_source.push_str("printf(\"%s\\n\", bufOut);");
} else {
c_source.push_str("write(1, bufOut, sizeof(bufOut));");
}
c_source.push_str("
return 0;
}");
Ok(c_source)
} else {
Err(())
}
}

257
src/c_gen_types.rs Normal file
View file

@ -0,0 +1,257 @@
use {
crate::{morphism::LdmcPrimMorph, struct_layout::{get_type_size, LayoutType, ObjectSize, StructLayout}}, chumsky::chain::Chain, laddertypes::{morphism::{Morphism, MorphismInstance}, morphism_sugared::{MorphismInstance2, SugaredMorphismType}, parser::*, substitution_sugared::SugaredSubstitution, unparser::*, Substitution, SugaredEnumVariant, SugaredStructMember, SugaredTypeTerm, TypeDict, TypeTerm}
};
/*
*/
pub fn get_c_repr_kind(kind: String) -> Option<String> {
match kind.as_str() {
"" => Some("uint64_t".into()),
_ => None
}
}
/* for a given ladder type `t`, get the corresponding C type
*/
pub fn get_c_repr_type(dict: &mut impl TypeDict, t: SugaredTypeTerm, skip_pointer: bool) -> Option<String> {
match t.get_floor_type().1.strip() {
SugaredTypeTerm::TypeID(tyid) => {
if tyid == dict.get_typeid_creat("native.UInt8") {
Some("uint8_t".into())
} else if tyid == dict.get_typeid_creat("native.UInt16") {
Some("uint16_t".into())
} else if tyid == dict.get_typeid_creat("native.UInt32") {
Some("uint32_t".into())
} else if tyid == dict.get_typeid_creat("native.UInt64") {
Some("uint64_t".into())
} else if tyid == dict.get_typeid_creat("native.Address") {
Some("void*".into())
} else if tyid == dict.get_typeid_creat("native.Float32") {
Some("float".into())
} else if tyid == dict.get_typeid_creat("native.Float64") {
Some("double".into())
} else {
None
}
}
SugaredTypeTerm::Seq{ seq_repr, items } => {
if let Some(sr_sugar) = seq_repr {
let sr = sr_sugar.desugar(dict);
let item_type = items.first().expect("no item type specified!").clone();
let item_c_type : String = get_c_repr_type(dict, item_type, false).expect("cant get item type representation");
dict.add_varname("Length".into()); // Kind: Num
dict.add_varname("LengthType".into()); // Kind: Type
dict.add_varname("TermValue".into()); // Kind: Value of Type ItemType
if let Ok(σ) = laddertypes::unify(
&sr,
&dict.parse("<StaticLength Length>").expect("parse")
) {
let length = match
σ.get(
&dict.get_typeid(&"Length".into()).expect("no Length ID")
).expect("no length specified!")
{
TypeTerm::Num(l) => l,
_ => {
eprintln!("invalid Length!");
return None;
}
};
Some(format!("{}[{}]", item_c_type, length))
}
else if let Ok(σ) = laddertypes::unify(
&sr,
&dict.parse("<LengthPrefix LengthType>").expect("parse")
) {
let length_type = σ.get(
&dict.get_typeid(&"LengthType".into()).expect("no LengthType ID")
).expect("no length type specified")
.clone()
.sugar(dict);
let length_c_type : String = get_c_repr_type(dict, length_type, false).expect("cant get length type representation");
match length_c_type.as_str() {
"uint8_t" |
"uint16_t" |
"uint32_t" |
"uint64_t" => {}
s => {
eprintln!("invalid length type '{}' !", s);
return None;
}
}
match item_c_type.as_str() {
"uint8_t" |
"uint16_t" |
"uint32_t" |
"uint64_t" |
"void*" => {}
s => {
eprintln!("invalid item type '{}'!", s);
return None;
}
}
Some(format!("LengthPrefix_{}_Array_{}", length_c_type, item_c_type))
}
else if let Ok(σ) = laddertypes::unify(
&sr,
&dict.parse("<ValueTerminated TermValue>").expect("")
) {
if skip_pointer {
Some(item_c_type)
} else {
Some(format!("{} *", item_c_type))
}
}
else {
eprintln!("can't get C-repr for sequence type `{}`!", dict.unparse(&sr));
None
}
} else {
eprintln!("no sequence-representation type specified!");
None
}
}
SugaredTypeTerm::Struct{ struct_repr, members } => {
let c_struct_attribute =
if let Some(sr) = struct_repr {
let sr = sr.desugar(dict);
match LayoutType::parse(dict, &sr).expect("layout type") {
LayoutType::Aligned => "",
LayoutType::Packed => "__attribute((packed))__"
}
} else {""};
let mut c_type = format!("struct {} {{\n", c_struct_attribute);
for SugaredStructMember{ symbol, ty } in members {
let field_c_type = get_c_repr_type(dict, ty, false).expect("");
c_type.push_str(&format!(" {} {};\n",
field_c_type,
symbol.replace("-", "_").replace(".","_dot_")
));
}
c_type.push_str("}");
Some(c_type)
}
SugaredTypeTerm::Enum { enum_repr, variants } => {
let mut c_type = format!("
struct {{
enum {{
");
for (i, SugaredEnumVariant{ symbol, ty }) in variants.iter().enumerate() {
c_type.push_str(&format!(
" {} = {}", symbol.replace("-", "_").replace(".","_dot_").to_uppercase(), i
));
if i+1 < variants.len() {
c_type.push_str(",\n");
}
}
c_type.push_str("
} tag;
union {
");
for SugaredEnumVariant{ symbol, ty } in variants {
let variant_c_type = get_c_repr_type(dict, ty, false).expect("cant get C-Repr type for variant");
c_type.push_str(&format!(
" {} {};\n", variant_c_type, symbol.replace("-", "_").replace(".","_dot_")
));
}
c_type.push_str("
};
}");
Some(c_type)
}
SugaredTypeTerm::Ladder(rungs) => {
if let Some(t) = rungs.last() {
get_c_repr_type(dict, t.clone(), false)
} else {
None
}
}
_ => { None }
}
}
pub fn encode_type_to_symbol(dict: &mut impl TypeDict, t: &laddertypes::SugaredTypeTerm)-> String {
let t = t.clone().desugar(dict);
match t {
laddertypes::TypeTerm::Char(c) => {
match c {
'.' => format!("_dot_"),
'-' => format!("_minus_"),
_ =>
format!("{}", (c as u64))
}
},
laddertypes::TypeTerm::Num(n) => {
format!("{}", n)
}
laddertypes::TypeTerm::TypeID(ty_id) => {
if let Some(name) = dict.get_typename(&ty_id) {
name
.replace("-", "_")
.replace(".", "_dot_")
} else {
format!("")
}
}
laddertypes::TypeTerm::Ladder(rs) |
laddertypes::TypeTerm::App(rs) => {
let mut s = String::new();
for r in rs {
s.push('_');
let r = r.sugar(dict);
s.push_str(&encode_type_to_symbol(dict, &r));
}
s
}
}
}
pub fn encode_type_to_arg_ty(dict: &mut impl TypeDict, t: &laddertypes::SugaredTypeTerm) -> String {
match t.get_floor_type().1 {
SugaredTypeTerm::Seq { seq_repr, items } => {
if let Some(seq_repr) = seq_repr {
if seq_repr.as_ref() == &dict.parse("<ValueTerminated 0>").expect("").sugar(dict) {
return encode_type_to_symbol(dict, items.first().unwrap());
}
}
}
_=>{}
}
encode_type_to_symbol(dict, t)
}
pub fn encode_morph_type_to_symbol(dict: &mut impl TypeDict, t: &SugaredMorphismType) -> String {
format!(
"morph_{}__to_{}",
encode_type_to_symbol(dict, &t.src_type),
encode_type_to_symbol(dict, &t.dst_type)
)
}
pub fn encode_type_to_value(dict: &mut impl TypeDict, t: &laddertypes::SugaredTypeTerm) -> String {
let t = t.clone().desugar(dict);
dict.unparse(&t)
}

View file

@ -3,30 +3,22 @@
mod morphism;
mod parser;
mod c_gen;
mod c_gen_types;
mod struct_layout;
use {
ariadne::{Color, Label, Report, ReportKind, Source},
chumsky::prelude::*,
laddertypes::{
parser::ParseLadderType, BimapTypeDict, MorphismType
},
std::sync::{Arc, RwLock},
tiny_ansi::TinyAnsi,
crate::{
morphism::LdmcMorphism,
morphism::LdmcPrimMorph,
parser::morphism_base_parser,
}
}, ariadne::{Color, Label, Report, ReportKind, Source}, c_gen::LdmcCTargetMorph, chumsky::prelude::*, laddertypes::{
morphism_path_sugared::SugaredShortestPathProblem, morphism_sugared::{MorphismInstance2, SugaredMorphism, SugaredMorphismType}, parser::ParseLadderType, unparser::*, BimapTypeDict, MorphismType, SugaredTypeTerm, TypeDict
}, std::{collections::HashMap, sync::{Arc, RwLock}}, tiny_ansi::TinyAnsi
};
fn main() {
let mut type_dict = Arc::new(RwLock::new(BimapTypeDict::new()));
let mut morphism_base = laddertypes::MorphismBase::<LdmcMorphism>::new(vec![
//type_dict.parse("Seq~MsbCont").expect(""),
//type_dict.parse("Seq~<ValueTerminated '\\0'>").expect(""),
type_dict.parse("Seq~<LengthPrefix native.UInt64>").expect("")
]);
let mut morphism_base = laddertypes::morphism_base_sugared::SugaredMorphismBase::<LdmcPrimMorph>::new();
let mut args = std::env::args().skip(1);
let src_type_arg = args.next().expect("src type expected");
@ -37,10 +29,10 @@ fn main() {
let result = morphism_base_parser(type_dict.clone()).parse(src.clone());
match result {
Ok((includes, morphisms)) => {
println!("{}",includes);
eprintln!("[{}] parse ok.", mb_path.bright_yellow());
println!("{}", includes);
for m in morphisms {
morphism_base.add_morphism(LdmcMorphism::Primitive(m));
morphism_base.add_morphism(m);
}
}
Err(errs) => {
@ -60,22 +52,50 @@ fn main() {
}
}
let mut γ = HashMap::new();
γ.insert(
type_dict.get_typeid_creat(&"Byte"),
type_dict.parse("<Seq~<StaticLength 8> Bit>").expect("parse")
.apply_subst(&γ)
.clone()
);
γ.insert(
type_dict.get_typeid_creat(&"x86.UInt8"),
type_dict.parse("_2^8 ~ <PosInt 2 BigEndian> ~ <Seq~<StaticLength 8> <Digit 2> ~ Bit>").expect("parse")
.apply_subst(&γ)
.clone()
);
γ.insert(
type_dict.get_typeid_creat(&"x86.UInt16"),
type_dict.parse("_2^16 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 2> <Digit 256> ~ x86.UInt8 >").expect("parse")
.apply_subst(&γ)
.clone()
);
γ.insert(
type_dict.get_typeid_creat(&"x86.UInt32"),
type_dict.parse("_2^32 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 4> <Digit 256> ~ x86.UInt8 >").expect("parse")
.apply_subst(&γ).clone()
);
γ.insert(
type_dict.get_typeid_creat(&"x86.UInt64"),
type_dict.parse("_2^64 ~ <PosInt 256 LittleEndian> ~ <Seq~<StaticLength 8> <Digit 256> ~ x86.UInt8 >").expect("parse")
.apply_subst(&γ).clone()
);
γ.insert(
type_dict.get_typeid_creat(&"x86.Float32"),
type_dict.parse(" ~ IEEE-754.Float32 ~ <Seq~<StaticLength 4> Byte>").expect("parse")
.apply_subst(&γ).clone()
);
γ.insert(
type_dict.get_typeid_creat(&"x86.Float64"),
type_dict.parse(" ~ IEEE-754.Float64 ~ <Seq~<StaticLength 4> Byte>").expect("parse")
.apply_subst(&γ).clone()
);
let src_type = type_dict.parse( src_type_arg.as_str() ).expect("");
let dst_type = type_dict.parse( dst_type_arg.as_str() ).expect("");
let path = morphism_base.find_morphism_path(MorphismType {
src_type: src_type.clone(),
dst_type: dst_type.clone(),
});
match path {
Some(path) => {
c_gen::generate_main(&mut type_dict, path, src_type, dst_type);
}
None => {
eprintln!("Error: could not find morphism path");
std::process::exit(-1);
}
}
let ty = SugaredMorphismType{ src_type: src_type.sugar(&mut type_dict), dst_type: dst_type.sugar(&mut type_dict) };
let m = morphism_base.get_morphism_instance( &ty ).expect("failed to find morphism");
println!("{}", crate::c_gen::generate_main(&mut type_dict, m).expect("failed to generate main function"));
}

View file

@ -1,28 +1,122 @@
use laddertypes::morphism::Morphism;
use laddertypes::{morphism::Morphism, morphism_base::MorphismBase, morphism_path::ShortestPathProblem, morphism_sugared::{SugaredMorphism, SugaredMorphismType}, SugaredStructMember};
use crate::{c_gen_types::encode_type_to_symbol, struct_layout::StructLayout};
#[derive(Clone, Debug)]
pub struct LdmcPrimCMorphism {
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct LdmcPrimMorph {
pub symbol: String,
pub type_args: Vec<(laddertypes::TypeID, String)>,
pub src_type: laddertypes::TypeTerm,
pub dst_type: laddertypes::TypeTerm,
pub ty: SugaredMorphismType,
pub c_source: String
}
#[derive(Clone)]
pub enum LdmcMorphism {
Primitive( LdmcPrimCMorphism ),
LengthPrefixMap{
length_prefix_type: laddertypes::TypeTerm,
item_morph: Box<LdmcPrimCMorphism>
},
ValueDelimMap{
delim: u64,
item_morph: Box<LdmcPrimCMorphism>
impl LdmcPrimMorph {
/*
pub fn into_prim_c_morphism(self, dict: &mut impl laddertypes::TypeDict, symbol: String) -> LdmcPrimCMorphism {
let src_c_type = ;
let dst_c_type = ;
let c_source =
format!("
int {} ( {} const * restrict src, {} * restrict dst ) {{
{}
return 0;
}}
",
symbol, src_c_type, dst_c_type,
self.generate_call(dict, &std::collections::HashMap::new(), 0)
);
LdmcPrimCMorphism {
symbol,
type_args: Vec::new(),
src_type,
dst_type,
c_source
}
}
*/
/*
pub fn new_struct_map(
dict: &mut impl laddertypes::TypeDict,
morph_base: &MorphismBase<LdmcPrimMorph>,
src: laddertypes::TypeTerm,
dst: laddertypes::TypeTerm,
) -> Self {
let src_struct = StructLayout::parse(dict, &src).expect("cant parse src struct layout");
let dst_struct = StructLayout::parse(dict, &dst).expect("cant parse dst struct layout");
let mut member_morphisms = Vec::new();
for SugaredStructMember{ symbol: field_name, ty: dst_type } in dst_struct.members.iter() {
let mut src_type = None;
for SugaredStructMember{ symbol: src_name, ty: st } in src_struct.members.iter() {
if src_name == field_name {
src_type = Some(st.clone());
}
}
let src_type = src_type.expect(&format!("cant find member {} in src struct", field_name));
if src_type == *dst_type {
member_morphisms.push(
StructFieldMorphism {
field_name: field_name.to_string(),
item_morph: None,
src_offset: src_struct.get_offset( field_name ),
dst_offset: dst_struct.get_offset( field_name ),
}
);
} else {
match ShortestPathProblem::new(
&morph_base,
laddertypes::MorphismType {
src_type: src_type.clone().desugar(dict),
dst_type: dst_type.clone().desugar(dict)
}
).solve()
{
Some(path) => {
let src_type = src_type.clone().desugar(dict);
let dst_type = dst_type.clone().desugar(dict);
let morph_symb = format!("morph_{}_to_{}",
encode_type_to_symbol(dict, &src_type),
encode_type_to_symbol(dict, &dst_type)
);
member_morphisms.push(
StructFieldMorphism {
field_name: field_name.to_string(),
item_morph: None,//Some(Box::new(item_morph.m.into_prim_c_morphism(dict, morph_symb, &item_morph.σ))),
src_offset: src_struct.get_offset( field_name ),
dst_offset: dst_struct.get_offset( field_name ),
}
);
},
None => {
eprintln!("cant map field {}", field_name);
}
}
}
}
LdmcPrimMorph::StructMap {
src_struct, dst_struct,
member_morphisms
}
}
*/
}
impl SugaredMorphism for LdmcPrimMorph {
fn get_type(&self) -> SugaredMorphismType {
self.ty.clone()
}
}
/*
impl Morphism for LdmcMorphism {
fn weight(&self) -> u64 {
1
@ -47,6 +141,12 @@ impl Morphism for LdmcMorphism {
src_type: laddertypes::TypeTerm::App(vec![ value_delim_type.clone(), item_morph.src_type.clone() ]),
dst_type: laddertypes::TypeTerm::App(vec![ value_delim_type.clone(), item_morph.dst_type.clone() ]),
}
},
LdmcMorphism::StructMap { src_struct, dst_struct, member_morphisms } => {
laddertypes::MorphismType {
src_type: src_struct.get_type(),
dst_type: dst_struct.get_type()
}
}
}.normalize()
}
@ -74,3 +174,4 @@ impl Morphism for LdmcMorphism {
}
}
}
*/

View file

@ -1,11 +1,7 @@
use {
chumsky::{
crate::morphism::LdmcPrimMorph, chumsky::{
prelude::*, text::*
},
std::sync::{Arc, RwLock},
laddertypes::{TypeDict, BimapTypeDict, parser::*},
crate::morphism::LdmcPrimCMorphism
}, laddertypes::{morphism_sugared::SugaredMorphismType, parser::*, BimapTypeDict, TypeDict}, std::sync::{Arc, RwLock}
};
/* morphism-base text format:
@ -18,7 +14,7 @@ use {
*/
pub fn morphism_base_parser(
type_dict: Arc<RwLock< BimapTypeDict >>
) -> impl Parser<char, (String, Vec<LdmcPrimCMorphism>), Error = Simple<char>> {
) -> impl Parser<char, (String, Vec<LdmcPrimMorph>), Error = Simple<char>> {
just("```")
.then(take_until(just("```")))
@ -63,14 +59,16 @@ pub fn morphism_base_parser(
ty_args.push((var_id, kind));
}
let src_type = type_dict.parse(&src_type.iter().collect::<String>()).expect("couldnt parse src type");
let dst_type = type_dict.parse(&dst_type.iter().collect::<String>()).expect("couldnt parse dst type");
let src_type = type_dict.parse(&src_type.iter().collect::<String>()).expect("couldnt parse src type").sugar(&mut *type_dict);
let dst_type = type_dict.parse(&dst_type.iter().collect::<String>()).expect("couldnt parse dst type").sugar(&mut *type_dict);
LdmcPrimCMorphism {
LdmcPrimMorph {
symbol,
type_args: ty_args,
src_type,
dst_type,
ty: SugaredMorphismType{
src_type,
dst_type
},
c_source
}
})

245
src/struct_layout.rs Normal file
View file

@ -0,0 +1,245 @@
use std::ops::Deref;
use laddertypes::{parser::*, unparser::*, SugaredStructMember, SugaredTypeTerm, TypeDict, TypeTerm};
#[derive(Clone, Copy, Debug)]
pub enum ObjectSize {
Static(u64),
Dynamic(/* function to get size at runtime */),
Unknown
}
impl std::ops::Add for ObjectSize {
type Output = Self;
fn add(self, rhs: Self) -> Self {
match (self, rhs) {
(ObjectSize::Unknown, _) |
(_, ObjectSize::Unknown)
=> ObjectSize::Unknown,
(ObjectSize::Dynamic(), _) |
(_, ObjectSize::Dynamic())
=> ObjectSize::Dynamic(),
(ObjectSize::Static(s1), ObjectSize::Static(s2)) => ObjectSize::Static(s1 + s2),
}
}
}
impl std::ops::Mul for ObjectSize {
type Output = Self;
fn mul(self, rhs: Self) -> Self {
match (self, rhs) {
(ObjectSize::Unknown, _) |
(_, ObjectSize::Unknown)
=> ObjectSize::Unknown,
(ObjectSize::Dynamic(), _) |
(_, ObjectSize::Dynamic())
=> ObjectSize::Dynamic(),
(ObjectSize::Static(s1), ObjectSize::Static(s2)) => ObjectSize::Static(s1 * s2),
}
}
}
pub fn get_type_size( dict: &mut impl TypeDict, ty: SugaredTypeTerm ) -> ObjectSize {
match &ty {
SugaredTypeTerm::TypeID(tyid) => {
if tyid == &dict.get_typeid_creat("native.UInt8") { ObjectSize::Static(1) }
else if tyid == &dict.get_typeid_creat("native.UInt16") { ObjectSize::Static(2) }
else if tyid == &dict.get_typeid_creat("native.UInt32") { ObjectSize::Static(4) }
else if tyid == &dict.get_typeid_creat("native.UInt64") { ObjectSize::Static(8) }
else if tyid == &dict.get_typeid_creat("native.Address") { ObjectSize::Static(8) }
else if tyid == &dict.get_typeid_creat("native.Float32") { ObjectSize::Static(4) }
else if tyid == &dict.get_typeid_creat("native.Float64") { ObjectSize::Static(8) }
else {
ObjectSize::Unknown
}
},
SugaredTypeTerm::Ladder(rungs) => {
get_type_size(dict, rungs.last().unwrap().clone() )
}
SugaredTypeTerm::Struct { struct_repr, members } => {
let layout = StructLayout::parse_sugared(dict, ty).expect("invalid struct");
layout.get_size()
}
SugaredTypeTerm::Seq { seq_repr, items } => {
if let Some(seq_repr) = seq_repr {
dict.add_typename("Length".into());
dict.add_typename("LengthType".into());
dict.add_typename("TerminatorValue".into());
if let Ok(σ) = laddertypes::unify(
&seq_repr.clone().desugar(dict),
&dict.parse("<StaticLength Length>").expect("")
) {
if let Some(TypeTerm::Num(len)) = σ.get(&dict.get_typeid(&"Length".into()).expect("")) {
ObjectSize::Static(*len as u64) * get_type_size(dict, items.first().unwrap().clone())
} else {
ObjectSize::Unknown
}
}
else if let Ok(σ) = laddertypes::unify(
&seq_repr.clone().desugar(dict),
&dict.parse("<LengthPrefix LengthType>").expect("")
) {
ObjectSize::Dynamic()
}
else if let Ok(σ) = laddertypes::unify(
&seq_repr.clone().desugar(dict),
&dict.parse("<ValueTerminated TerminatorValue>").expect("")
) {
ObjectSize::Dynamic()
}
else {
ObjectSize::Unknown
}
} else {
ObjectSize::Unknown
}
}
_ => ObjectSize::Unknown
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum LayoutType {
Aligned,
Packed
}
impl LayoutType {
pub fn parse( dict: &mut impl TypeDict, ty: &TypeTerm ) -> Option< LayoutType > {
if ty == &dict.parse("Aligned").expect("parse") {
Some(LayoutType::Aligned)
} else if ty == &dict.parse("Packed").expect("parse") {
Some(LayoutType::Packed)
} else {
None
}
}
pub fn unparse(&self, dict: &mut impl TypeDict) -> TypeTerm {
match self {
LayoutType::Aligned => dict.parse("Aligned").unwrap(),
LayoutType::Packed => dict.parse("Packed").unwrap()
}
}
}
#[derive(Clone)]
pub struct StructLayout {
pub ty: laddertypes::TypeTerm,
pub layout: LayoutType,
pub members: Vec< SugaredStructMember >,
offsets: std::collections::HashMap< String, u64 >,
size: ObjectSize
}
impl StructLayout {
pub fn get_type(&self) -> TypeTerm {
self.ty.clone()
}
pub fn get_size(&self) -> ObjectSize {
self.size
}
pub fn get_offset(&self, name: &String) -> u64 {
*self.offsets.get(name).expect("")
}
pub fn init_offsets(&mut self, dict: &mut impl TypeDict) {
let mut offset = 0;
for SugaredStructMember{symbol: field_name, ty: field_type} in self.members.iter() {
//let field_c_type = crate::c_gen::get_c_repr_type(dict, field_type.clone(), true).expect("cant get c-repr for struct field");
match get_type_size( dict, field_type.clone() ) {
ObjectSize::Static(field_size) => {
match self.layout {
LayoutType::Aligned => {
// add padding to get natural alignment of current member
if offset % field_size > 0 {
offset = field_size * ((offset / field_size)+1);
}
}
LayoutType::Packed => {
// no padding
}
}
// take offset
self.offsets.insert(field_name.clone(), offset);
// advance by current size
offset += field_size;
}
ObjectSize::Dynamic() => {
eprintln!("dynamically sized Field in struct!");
self.offsets.insert(field_name.clone(), offset);
self.size = ObjectSize::Dynamic();
return;
}
ObjectSize::Unknown => {
eprintln!("Struct member `{}` has unknown size!", field_name);
self.offsets.insert(field_name.clone(), offset);
self.size = ObjectSize::Unknown;
return;
}
}
}
match self.size {
ObjectSize::Dynamic() => {
}
_ => {
self.size = ObjectSize::Static(offset);
}
}
}
pub fn parse(dict: &mut impl TypeDict, struct_type: &TypeTerm) -> Option <Self> {
let st = struct_type.clone().strip().param_normalize().sugar(dict);
Self::parse_sugared(dict, st)
}
pub fn parse_sugared(dict: &mut impl TypeDict, st: SugaredTypeTerm) -> Option <Self> {
eprintln!("{}", st.pretty(dict, 0));
match st.clone() {
SugaredTypeTerm::Struct{ struct_repr, members } => {
let mut sl = StructLayout {
ty: st.desugar(dict),
layout: if let Some(sr) = struct_repr {
let sr = sr.desugar(dict);
LayoutType::parse( dict, &sr ).expect("invalid struct layout type")
} else {
eprintln!("choose default struct repr");
LayoutType::Aligned
},
members,
offsets: std::collections::HashMap::new(),
size: ObjectSize::Unknown
};
sl.init_offsets(dict);
Some(sl)
}
_ => {
eprintln!("not a struct");
None
}
}
}
}