@@ 1,5 1,8 @@
//! A place for us to stick compiler builtins and the metadata they need,
//! instead of having them scattered all over.
+//!
+//! TODO: We would really benefit from having a function that can take in a single
+//! number type and output all the math/binary/logic ops for that number.
use std::collections::BTreeMap;
@@ 16,12 19,139 @@ pub struct Builtin {
pub sig: Type,
/// The implmentation of the builtin as raw code for each particular
/// backend.
- pub code: BTreeMap<Backend, &'static str>,
+ pub code: BTreeMap<Backend, String>,
}
pub static BUILTINS: Lazy<Vec<Builtin>> = Lazy::new(Builtin::all);
impl Builtin {
+ /// Generate all appropriate methods for the given numeric type.
+ /// Right now we just stick em in the toplevel with constructed names,
+ /// but eventually they'll have to go into their own module/package/whatever.
+ /// That package will still contain these generated strings though, so oh well.
+ ///
+ /// I guess this is the start of Garnet's macro system, huh?
+ ///
+ /// TODO: rotates, arithmetic shift, wrapping stuff, other?
+ fn generate_numerics_for(name: &str, ty: Type) -> Vec<Builtin> {
+ // names come from luajit I suppose
+ // I'm not in love wtih 'em but also don't want to think about em.
+ let println = format!(
+ r#"
+fn __println_{name}(x: {name}) {{
+ println!("{{}}", x);
+}}"#
+ );
+ let band = format!(
+ r#"
+fn __band_{name}(x: {name}, y: {name}) -> {name} {{
+ x & y
+}}"#
+ );
+ let bor = format!(
+ r#"
+fn __bor_{name}(x: {name}, y: {name}) -> {name} {{
+ x | y
+}}"#
+ );
+ let bxor = format!(
+ r#"
+fn __bxor_{name}(x: {name}, y: {name}) -> {name} {{
+ x ^ y
+}}"#
+ );
+ let bnot = format!(
+ r#"
+fn __bnot_{name}(x: {name}) -> {name} {{
+ !x
+}}"#
+ );
+
+ let rshift = format!(
+ r#"
+fn __rshift_{name}(x: {name}, i: {name}) -> {name} {{
+ x >> i
+}}"#
+ );
+ let lshift = format!(
+ r#"
+fn __lshift_{name}(x: {name}, i: {name}) -> {name} {{
+ x << i
+}}"#
+ );
+ let rol = format!(
+ r#"
+fn __rol_{name}(x: {name}, i: i32) -> {name} {{
+ x.rotate_left(i as u32)
+}}"#
+ );
+ let ror = format!(
+ r#"
+fn __ror_{name}(x: {name}, i: i32) -> {name} {{
+ x.rotate_right(i as u32)
+}}"#
+ );
+
+ let cast_i32 = format!(
+ r#"
+fn __{name}_to_i32(x: {name}) -> i32 {{
+ x as i32
+}}"#
+ );
+
+ vec![
+ Builtin {
+ name: Sym::new(format!("__println_{name}")),
+ sig: Type::Func(vec![ty.clone()], Box::new(Type::unit()), vec![]),
+ code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, println)]),
+ },
+ Builtin {
+ name: Sym::new(format!("__band_{name}")),
+ sig: Type::Func(vec![ty.clone(), ty.clone()], Box::new(ty.clone()), vec![]),
+ code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, band)]),
+ },
+ Builtin {
+ name: Sym::new(format!("__bor_{name}")),
+ sig: Type::Func(vec![ty.clone(), ty.clone()], Box::new(ty.clone()), vec![]),
+ code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, bor)]),
+ },
+ Builtin {
+ name: Sym::new(format!("__bxor_{name}")),
+ sig: Type::Func(vec![ty.clone(), ty.clone()], Box::new(ty.clone()), vec![]),
+ code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, bxor)]),
+ },
+ Builtin {
+ name: Sym::new(format!("__bnot_{name}")),
+ sig: Type::Func(vec![ty.clone()], Box::new(ty.clone()), vec![]),
+ code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, bnot)]),
+ },
+ Builtin {
+ name: Sym::new(format!("__rshift_{name}")),
+ sig: Type::Func(vec![ty.clone(), ty.clone()], Box::new(ty.clone()), vec![]),
+ code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, rshift)]),
+ },
+ Builtin {
+ name: Sym::new(format!("__lshift_{name}")),
+ sig: Type::Func(vec![ty.clone(), ty.clone()], Box::new(ty.clone()), vec![]),
+ code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, lshift)]),
+ },
+ Builtin {
+ name: Sym::new(format!("__rol_{name}")),
+ sig: Type::Func(vec![ty.clone(), Type::i32()], Box::new(ty.clone()), vec![]),
+ code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, rol)]),
+ },
+ Builtin {
+ name: Sym::new(format!("__ror_{name}")),
+ sig: Type::Func(vec![ty.clone(), Type::i32()], Box::new(ty.clone()), vec![]),
+ code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, ror)]),
+ },
+ Builtin {
+ name: Sym::new(format!("__{name}_to_i32")),
+ sig: Type::Func(vec![ty.clone()], Box::new(Type::i32()), vec![]),
+ code: BTreeMap::from([(Backend::Null, "".into()), (Backend::Rust, cast_i32)]),
+ },
+ ]
+ }
/// A function that returns all the compiler builtin info. Just
/// use the `BUILTINS` global instead, this is basically here
/// to initialize it.
@@ 34,112 164,28 @@ fn __println_bool(x: bool) {
println!("{}", x);
}"#;
- let rust_println_i64 = r#"
-fn __println_i64(x: i64) {
- println!("{}", x);
-}"#;
- let rust_println_i16 = r#"
-fn __println_i16(x: i16) {
- println!("{}", x);
-}"#;
-
- let band = r#"
-fn __band(x: i32, y: i32) -> i32 {
- x & y
-}"#;
- let bor = r#"
-fn __bor(x: i32, y: i32) -> i32 {
- x | y
-}"#;
- let bxor = r#"
-fn __bxor(x: i32, y: i32) -> i32 {
- x ^ y
-}"#;
- let bnot = r#"
-fn __bnot(x: i32) -> i32 {
- !x
-}"#;
-
- let rshift = r#"
-fn __rshift(x: i32, i: i32) -> i32 {
- x >> i
-}"#;
- let lshift = r#"
-fn __lshift(x: i32, i: i32) -> i32 {
- x << i
-}"#;
- vec![
+ let mut funcs = vec![
Builtin {
name: Sym::new("__println"),
sig: Type::Func(vec![Type::i32()], Box::new(Type::unit()), vec![]),
- code: BTreeMap::from([(Backend::Null, ""), (Backend::Rust, rust_println)]),
+ code: BTreeMap::from([
+ (Backend::Null, "".into()),
+ (Backend::Rust, rust_println.into()),
+ ]),
},
Builtin {
name: Sym::new("__println_bool"),
sig: Type::Func(vec![Type::bool()], Box::new(Type::unit()), vec![]),
- code: BTreeMap::from([(Backend::Null, ""), (Backend::Rust, rust_println_bool)]),
- },
- Builtin {
- name: Sym::new("__println_i64"),
- sig: Type::Func(vec![Type::i64()], Box::new(Type::unit()), vec![]),
- code: BTreeMap::from([(Backend::Null, ""), (Backend::Rust, rust_println_i64)]),
- },
- Builtin {
- name: Sym::new("__println_i16"),
- sig: Type::Func(vec![Type::i16()], Box::new(Type::unit()), vec![]),
- code: BTreeMap::from([(Backend::Null, ""), (Backend::Rust, rust_println_i16)]),
- },
- // names come from luajit I suppose
- Builtin {
- name: Sym::new("__band"),
- sig: Type::Func(
- vec![Type::i32(), Type::i32()],
- Box::new(Type::i32()),
- vec![],
- ),
- code: BTreeMap::from([(Backend::Null, ""), (Backend::Rust, band)]),
- },
- Builtin {
- name: Sym::new("__bor"),
- sig: Type::Func(
- vec![Type::i32(), Type::i32()],
- Box::new(Type::i32()),
- vec![],
- ),
- code: BTreeMap::from([(Backend::Null, ""), (Backend::Rust, bor)]),
+ code: BTreeMap::from([
+ (Backend::Null, "".into()),
+ (Backend::Rust, rust_println_bool.into()),
+ ]),
},
- Builtin {
- name: Sym::new("__bxor"),
- sig: Type::Func(
- vec![Type::i32(), Type::i32()],
- Box::new(Type::i32()),
- vec![],
- ),
- code: BTreeMap::from([(Backend::Null, ""), (Backend::Rust, bxor)]),
- },
- Builtin {
- name: Sym::new("__bnot"),
- sig: Type::Func(vec![Type::i32()], Box::new(Type::i32()), vec![]),
- code: BTreeMap::from([(Backend::Null, ""), (Backend::Rust, bnot)]),
- },
- Builtin {
- name: Sym::new("__rshift"),
- sig: Type::Func(
- vec![Type::i32(), Type::i32()],
- Box::new(Type::i32()),
- vec![],
- ),
- code: BTreeMap::from([(Backend::Null, ""), (Backend::Rust, rshift)]),
- },
- Builtin {
- name: Sym::new("__lshift"),
- sig: Type::Func(
- vec![Type::i32(), Type::i32()],
- Box::new(Type::i32()),
- vec![],
- ),
- code: BTreeMap::from([(Backend::Null, ""), (Backend::Rust, lshift)]),
- },
- ]
+ ];
+ funcs.extend(Self::generate_numerics_for("i8", Type::i8()));
+ funcs.extend(Self::generate_numerics_for("i16", Type::i16()));
+ funcs.extend(Self::generate_numerics_for("i32", Type::i32()));
+ funcs.extend(Self::generate_numerics_for("i64", Type::i64()));
+ funcs
}
}
@@ 33,16 33,21 @@ fn unparse_decl(d: &Decl, out: &mut dyn
doc_comment,
} => {
for line in doc_comment.iter() {
- write!(out, "--- {}", line)?;
+ write!(out, "---{}", line)?;
}
let name = name.val();
let tname = typename.get_name();
write!(out, "const {} {} = ", name, tname)?;
unparse_expr(init, 0, out)
}
- Decl::TypeDef { name, params, typedecl, doc_comment } => {
+ Decl::TypeDef {
+ name,
+ params,
+ typedecl,
+ doc_comment,
+ } => {
for line in doc_comment.iter() {
- write!(out, "--- {}", line)?;
+ write!(out, "---{}", line)?;
}
let name = name.val();
let tname = typedecl.get_name();
@@ 63,7 68,6 @@ fn unparse_decl(d: &Decl, out: &mut dyn
writeln!(out, "type {}({}) = {}", name, paramstr, tname)?;
}
writeln!(out)
-
}
Decl::Import { name, rename } => {
if let Some(re) = rename {
@@ 89,9 93,9 @@ fn unparse_sig(sig: &Signature, out: &mu
}
write!(out, "{}", name.get_name())?;
}
- write!(out, "| ")?;
+ write!(out, "| ")?;
}
-
+
// Write (foo I32, bar I16)
// not (foo I32, bar I16, )
let mut first = true;