Get some basic alignment sorting going

This commit is contained in:
Richard Feldman 2022-03-26 14:38:27 -04:00
parent afd232281c
commit 89385d05d1
No known key found for this signature in database
GPG Key ID: 7E4127D1E4241798
6 changed files with 121 additions and 70 deletions

1
Cargo.lock generated
View File

@ -3438,6 +3438,7 @@ version = "0.1.0"
dependencies = [
"indoc",
"pretty_assertions",
"roc_std",
]
[[package]]

View File

@ -6,6 +6,7 @@ license = "UPL-1.0"
edition = "2018"
[dependencies]
roc_std = { path = "../roc_std" }
[dev-dependencies]
pretty_assertions = "1.0.0"

View File

@ -1,5 +1,10 @@
use crate::enums::Enums;
use crate::structs::Structs;
use crate::types::RocType;
use std::{fmt::Write, io};
use std::{
fmt::{self, Write},
io,
};
static TEMPLATE: &[u8] = include_bytes!("../templates/template.rs");
static INDENT: &str = " ";
@ -32,69 +37,34 @@ pub fn write_bindings(_writer: &mut impl io::Write) -> io::Result<()> {
// pub fn declare_roc_type(roc_type: RocType, uid: &mut u32, buf: &mut String) {
// }
pub fn roc_type(roc_type: RocType, buf: &mut String) {
pub fn write_roc_type(
roc_type: RocType,
structs: &mut Structs,
enums: &mut Enums,
buf: &mut String,
) -> fmt::Result {
match roc_type {
RocType::Str => {
// TODO
}
RocType::Bool => {
// TODO
}
RocType::List(/*Box<RocType>*/) => {
// TODO
}
RocType::TagUnion(/*Vec<(String, Vec<RocType>)>*/) => {
// TODO
}
// RocType::Record(Vec<(String, Box<RocType>)>) => {
// *uid += 1;
// buf.write_str(&format!("struct S{} {", *uid));
// for (field_name, field_type) in fields.into_iter() {
// buf.write_str(INDENT);
// declare_roc_type
// }
// buf.write('}');
// }
RocType::I8 => {
buf.write_str("i8");
}
RocType::U8 => {
buf.write_str("u8");
}
RocType::I16 => {
buf.write_str("i16");
}
RocType::U16 => {
buf.write_str("u16");
}
RocType::I32 => {
buf.write_str("i32");
}
RocType::U32 => {
buf.write_str("u32");
}
RocType::I64 => {
buf.write_str("i64");
}
RocType::U64 => {
buf.write_str("u64");
}
RocType::I128 => {
buf.write_str("i128");
}
RocType::U128 => {
buf.write_str("u128");
}
RocType::F32 => {
buf.write_str("f32");
}
RocType::F64 => {
buf.write_str("f64");
}
RocType::Dec => {
buf.write_str("RocDec");
RocType::Bool => buf.write_str("bool"),
RocType::I8 => buf.write_str("i8"),
RocType::U8 => buf.write_str("u8"),
RocType::I16 => buf.write_str("i16"),
RocType::U16 => buf.write_str("u16"),
RocType::I32 => buf.write_str("i32"),
RocType::U32 => buf.write_str("u32"),
RocType::I64 => buf.write_str("i64"),
RocType::U64 => buf.write_str("u64"),
RocType::I128 => buf.write_str("i128"),
RocType::U128 => buf.write_str("u128"),
RocType::F32 => buf.write_str("f32"),
RocType::F64 => buf.write_str("f64"),
RocType::Dec => buf.write_str("RocDec"),
RocType::Str => buf.write_str("RocStr"),
RocType::List(elem_type) => {
buf.write_str("RocList<")?;
write_roc_type(*elem_type, structs, enums, buf)?;
buf.write_char('>')
}
RocType::TagUnion(tag_union) => buf.write_str(&enums.get_name(&tag_union)),
RocType::Record(record) => buf.write_str(&structs.get_name(&record)),
}
}

View File

@ -1,5 +1,6 @@
// pub mod bindgen_c;
// pub mod bindgen_rs;
// pub mod bindgen_zig;
pub mod bindgen_c;
pub mod bindgen_rs;
pub mod bindgen_zig;
mod enums;
mod structs;
mod types;

View File

@ -1,4 +1,4 @@
use crate::types::{RocRecord, RocType};
use crate::types::RocRecord;
use std::collections::HashMap;
#[derive(Copy, Clone, Debug)]
@ -6,12 +6,12 @@ struct StructId(u64);
impl StructId {
pub fn to_name(self) -> String {
format!("S{}", self.0)
format!("R{}", self.0)
}
}
/// Whenever we register a new record type,
/// give it a unique and short name (e.g. S1, S2, S3...)
/// give it a unique and short name (e.g. R1, R2, R3...)
/// and then from then on, whenever we ask for that
/// same record type, return the same name.
pub struct Structs {

View File

@ -1,9 +1,12 @@
use core::mem;
use roc_std::{RocDec, RocList, RocStr};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum RocType {
Str,
Bool,
List(Box<RocType>),
TagUnion(Vec<(String, Vec<RocType>)>),
TagUnion(RocTagUnion),
Record(RocRecord),
I8,
U8,
@ -20,6 +23,31 @@ pub enum RocType {
Dec,
}
impl RocType {
pub fn alignment(&self) -> usize {
match self {
RocType::Str => mem::align_of::<RocStr>(),
RocType::List(_) => mem::align_of::<RocList<()>>(),
RocType::Dec => mem::align_of::<RocDec>(),
RocType::Bool => mem::align_of::<bool>(),
RocType::TagUnion(tag_union) => tag_union.alignment(),
RocType::Record(record) => record.alignment(),
RocType::I8 => mem::align_of::<i8>(),
RocType::U8 => mem::align_of::<u8>(),
RocType::I16 => mem::align_of::<i16>(),
RocType::U16 => mem::align_of::<u16>(),
RocType::I32 => mem::align_of::<i32>(),
RocType::U32 => mem::align_of::<u32>(),
RocType::I64 => mem::align_of::<i64>(),
RocType::U64 => mem::align_of::<u64>(),
RocType::I128 => mem::align_of::<i128>(),
RocType::U128 => mem::align_of::<u128>(),
RocType::F32 => mem::align_of::<f32>(),
RocType::F64 => mem::align_of::<f64>(),
}
}
}
#[derive(Default, Debug, Clone, PartialEq, Eq, Hash)]
pub struct RocRecord {
fields: Vec<(String, Box<RocType>)>,
@ -33,4 +61,54 @@ impl RocRecord {
pub fn into_fields(self) -> Vec<(String, Box<RocType>)> {
self.fields
}
pub fn alignment(&self) -> usize {
let mut align = 0;
for (_, field_type) in self.fields.iter() {
align = align.max(field_type.alignment())
}
align
}
/// Use struct ordering, taking into account alignment and alphabetization.
pub fn use_struct_ordering(&mut self) {
self.fields.sort_by(|(field1, type1), (field2, type2)| {
let align1 = type1.alignment();
let align2 = type2.alignment();
if align1 == align2 {
field1.cmp(field2)
} else {
align1.cmp(&align2)
}
});
}
}
#[derive(Default, Debug, Clone, PartialEq, Eq, Hash)]
pub struct RocTagUnion {
tags: Vec<(String, Vec<RocType>)>,
}
impl RocTagUnion {
pub fn new(tags: Vec<(String, Vec<RocType>)>) -> Self {
Self { tags }
}
pub fn into_tags(self) -> Vec<(String, Vec<RocType>)> {
self.tags
}
pub fn alignment(&self) -> usize {
let mut align = 0;
for (_, args) in self.tags.iter() {
for arg in args {
align = align.max(arg.alignment())
}
}
align
}
}