Compare commits
6 Commits
f700c577f1
...
2303bf757a
Author | SHA1 | Date | |
---|---|---|---|
2303bf757a | |||
7234cad5f0 | |||
baa068a371 | |||
8b1d1084a6 | |||
f5f55079a9 | |||
baa7bafafc |
@ -1,5 +1,8 @@
|
||||
import std::String;
|
||||
import std::print;
|
||||
|
||||
fn main() -> u8 {
|
||||
// let message = String::from(include_bytes!("./macro_easy_file.txt"));
|
||||
let bytes = test_macro!("./examples/macro_easy_file.txt");
|
||||
return bytes[0];
|
||||
let bytes = include_bytes!("./macro_easy_file.txt");
|
||||
print(String::new() + bytes.length());
|
||||
return (bytes as *u8)[0];
|
||||
}
|
||||
|
@ -58,6 +58,28 @@ pub fn form_intrinsics() -> Vec<FunctionDefinition> {
|
||||
}
|
||||
|
||||
pub fn get_intrinsic_assoc_func(ty: &TypeKind, name: &str) -> Option<FunctionDefinition> {
|
||||
if let TypeKind::Array(_, len) = ty {
|
||||
match name {
|
||||
"length" => {
|
||||
return Some(FunctionDefinition {
|
||||
name: "length".to_owned(),
|
||||
linkage_name: None,
|
||||
is_pub: true,
|
||||
is_imported: false,
|
||||
return_type: TypeKind::U64,
|
||||
parameters: vec![FunctionParam {
|
||||
name: String::from("self"),
|
||||
ty: TypeKind::Borrow(Box::new(ty.clone()), false),
|
||||
meta: Default::default(),
|
||||
}],
|
||||
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicConst(*len))),
|
||||
source: None,
|
||||
})
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
match name {
|
||||
"sizeof" => Some(FunctionDefinition {
|
||||
name: "sizeof".to_owned(),
|
||||
@ -408,6 +430,14 @@ impl IntrinsicFunction for IntrinsicNullPtr {
|
||||
))
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct IntrinsicConst(u64);
|
||||
impl IntrinsicFunction for IntrinsicConst {
|
||||
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, _: &[StackValue]) -> Result<StackValue, ErrorKind> {
|
||||
let zero = scope.block.build(Instr::Constant(ConstValueKind::U64(self.0))).unwrap();
|
||||
Ok(StackValue(StackValueKind::Literal(zero), TypeKind::U64))
|
||||
}
|
||||
}
|
||||
|
||||
// impl IntrinsicFunction for IntrinsicIAdd {
|
||||
// fn codegen<'ctx, 'a>(
|
||||
|
@ -1313,7 +1313,7 @@ impl mir::Expression {
|
||||
Some(val)
|
||||
} else {
|
||||
match (&val.1, type_kind) {
|
||||
(TypeKind::CodegenPtr(inner), TypeKind::UserPtr(_)) => match *inner.clone() {
|
||||
(TypeKind::CodegenPtr(inner), TypeKind::UserPtr(ty2)) => match *inner.clone() {
|
||||
TypeKind::UserPtr(_) => Some(StackValue(
|
||||
val.0.derive(
|
||||
scope
|
||||
@ -1326,6 +1326,27 @@ impl mir::Expression {
|
||||
),
|
||||
TypeKind::CodegenPtr(Box::new(type_kind.clone())),
|
||||
)),
|
||||
TypeKind::Borrow(ty1, _) => match *ty1.clone() {
|
||||
TypeKind::Array(ty1, _) => {
|
||||
if ty1 == *ty2 {
|
||||
Some(StackValue(
|
||||
val.0.derive(
|
||||
scope
|
||||
.block
|
||||
.build(Instr::BitCast(
|
||||
val.instr(),
|
||||
Type::Ptr(Box::new(type_kind.get_type(scope.type_values))),
|
||||
))
|
||||
.unwrap(),
|
||||
),
|
||||
TypeKind::CodegenPtr(Box::new(type_kind.clone())),
|
||||
))
|
||||
} else {
|
||||
return Err(ErrorKind::Null);
|
||||
}
|
||||
}
|
||||
_ => return Err(ErrorKind::Null),
|
||||
},
|
||||
_ => panic!(),
|
||||
},
|
||||
(TypeKind::UserPtr(_), TypeKind::UserPtr(_))
|
||||
@ -1360,7 +1381,7 @@ impl mir::Expression {
|
||||
let global_value = scope.globals.get(global_name).unwrap();
|
||||
let a = Some(StackValue(
|
||||
StackValueKind::Literal(scope.block.build(Instr::GetGlobal(global_value.clone())).unwrap()),
|
||||
TypeKind::UserPtr(Box::new(ty.clone())),
|
||||
ty.clone(),
|
||||
));
|
||||
a
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ pub struct ErrorModule {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||
pub struct ErrorModules {
|
||||
module_map: HashMap<mir::SourceModuleId, ErrorModule>,
|
||||
pub(super) module_map: HashMap<mir::SourceModuleId, ErrorModule>,
|
||||
module_counter: mir::SourceModuleId,
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
||||
//! - Debug Symbols
|
||||
//! ```
|
||||
|
||||
use std::{path::PathBuf, thread, time::Duration};
|
||||
use std::{collections::HashMap, path::PathBuf, thread, time::Duration};
|
||||
|
||||
use ast::{
|
||||
lexer::{self, FullToken, Token},
|
||||
@ -58,7 +58,7 @@ use reid_lib::{compile::CompileOutput, Context};
|
||||
|
||||
use crate::{
|
||||
ast::TopLevelStatement,
|
||||
mir::macros::{form_macros, MacroPass},
|
||||
mir::macros::{form_macros, MacroModule, MacroPass},
|
||||
};
|
||||
|
||||
mod ast;
|
||||
@ -156,7 +156,16 @@ pub fn perform_all_passes<'map>(
|
||||
));
|
||||
}
|
||||
|
||||
let state = context.pass(&mut MacroPass { macros: form_macros() })?;
|
||||
let mut macro_modules: HashMap<_, MacroModule> = HashMap::new();
|
||||
for (k, v) in &context.modules {
|
||||
macro_modules.insert(k.clone(), v.into());
|
||||
}
|
||||
|
||||
let mut macro_pass = MacroPass {
|
||||
macros: form_macros(),
|
||||
module_map: macro_modules,
|
||||
};
|
||||
let state = context.pass(&mut macro_pass)?;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
println!("{:-^100}", "MACRO OUTPUT");
|
||||
|
@ -49,6 +49,9 @@ impl Display for Module {
|
||||
for typedef in &self.typedefs {
|
||||
writeln!(inner_f, "{}", typedef)?;
|
||||
}
|
||||
for global in &self.globals {
|
||||
writeln!(inner_f, "global {} = {}", global.name, global.kind)?;
|
||||
}
|
||||
for (ty, fun) in &self.associated_functions {
|
||||
writeln!(inner_f, "(Assoc {}) {}", ty, fun)?;
|
||||
}
|
||||
@ -59,6 +62,26 @@ impl Display for Module {
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for GlobalKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
GlobalKind::Literal(literal) => Display::fmt(literal, f),
|
||||
GlobalKind::Array(global_kinds) => {
|
||||
f.write_char('[')?;
|
||||
let mut iter = global_kinds.iter();
|
||||
if let Some(global) = iter.next() {
|
||||
Display::fmt(global, f)?;
|
||||
while let Some(global) = iter.next() {
|
||||
write!(f, ", ")?;
|
||||
Display::fmt(global, f)?;
|
||||
}
|
||||
}
|
||||
f.write_char(']')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Import {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "import {}", self.0.join("::"))
|
||||
@ -280,7 +303,7 @@ impl Display for ExprKind {
|
||||
write!(f, "::")?;
|
||||
Display::fmt(function_call, f)
|
||||
}
|
||||
ExprKind::GlobalRef(global_value, type_kind) => write!(f, "todo globals"),
|
||||
ExprKind::GlobalRef(global_value, type_kind) => write!(f, "global<{}>(${})", type_kind, global_value),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -429,7 +429,7 @@ impl Expression {
|
||||
Err(_) => Ok((ReturnKind::Soft, type_kind.clone())),
|
||||
},
|
||||
AssociatedFunctionCall(_, fcall) => fcall.return_type(),
|
||||
GlobalRef(_, type_kind) => Ok((ReturnKind::Soft, TypeKind::UserPtr(Box::new(type_kind.clone())))),
|
||||
GlobalRef(_, type_kind) => Ok((ReturnKind::Soft, type_kind.clone())),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,19 @@
|
||||
use std::collections::HashMap;
|
||||
use std::{collections::HashMap, path::PathBuf};
|
||||
|
||||
use crate::mir::{self, FunctionCall, GlobalKind, GlobalValue, IfExpression, Literal, TypeKind, WhileStatement};
|
||||
use crate::mir::{
|
||||
self, FunctionCall, GlobalKind, GlobalValue, IfExpression, Literal, Module, SourceModuleId, TypeKind,
|
||||
WhileStatement,
|
||||
};
|
||||
|
||||
use super::pass::{Pass, PassResult, PassState};
|
||||
|
||||
pub trait MacroFunction: std::fmt::Debug {
|
||||
fn generate<'ctx, 'a>(&self, params: &[mir::Literal]) -> Result<(Vec<GlobalValue>, mir::ExprKind), ErrorKind>;
|
||||
fn generate<'ctx, 'a>(
|
||||
&self,
|
||||
module: &MacroModule,
|
||||
params: &[mir::Literal],
|
||||
prefix: String,
|
||||
) -> Result<(Vec<GlobalValue>, mir::ExprKind), ErrorKind>;
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
@ -24,13 +32,28 @@ pub enum ErrorKind {
|
||||
MacroExecutionError(String),
|
||||
}
|
||||
|
||||
type MacroModuleMap = HashMap<SourceModuleId, MacroModule>;
|
||||
|
||||
/// Struct used to implement a type-checking pass that can be performed on the
|
||||
/// MIR.
|
||||
pub struct MacroPass {
|
||||
pub(crate) macros: HashMap<String, Box<dyn MacroFunction>>,
|
||||
pub module_map: MacroModuleMap,
|
||||
}
|
||||
|
||||
type MacroPassState<'st, 'sc> = PassState<'st, 'sc, (), ErrorKind>;
|
||||
pub struct MacroModule {
|
||||
path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl From<&Module> for MacroModule {
|
||||
fn from(value: &Module) -> Self {
|
||||
MacroModule {
|
||||
path: value.path.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type MacroPassState<'map, 'st, 'sc> = PassState<'st, 'sc, (), ErrorKind>;
|
||||
|
||||
impl Pass for MacroPass {
|
||||
type Data = ();
|
||||
@ -43,7 +66,7 @@ impl Pass for MacroPass {
|
||||
fn module(&mut self, module: &mut mir::Module, mut state: PassState<Self::Data, Self::TError>) -> PassResult {
|
||||
for function in &mut module.functions {
|
||||
let globals = match &mut function.kind {
|
||||
mir::FunctionDefinitionKind::Local(block, _) => block.gen_macros(self, &mut state),
|
||||
mir::FunctionDefinitionKind::Local(block, _) => block.gen_macros(self, &mut state, &self.module_map),
|
||||
_ => Vec::new(),
|
||||
};
|
||||
|
||||
@ -54,36 +77,36 @@ impl Pass for MacroPass {
|
||||
}
|
||||
|
||||
impl mir::Block {
|
||||
fn gen_macros(&mut self, data: &MacroPass, state: &mut MacroPassState) -> Vec<GlobalValue> {
|
||||
fn gen_macros(&mut self, data: &MacroPass, state: &mut MacroPassState, map: &MacroModuleMap) -> Vec<GlobalValue> {
|
||||
let mut globals = Vec::new();
|
||||
for statement in &mut self.statements {
|
||||
globals.extend(statement.gen_macros(data, state));
|
||||
globals.extend(statement.gen_macros(data, state, map));
|
||||
}
|
||||
if let Some((_, Some(return_expr))) = &mut self.return_expression {
|
||||
globals.extend(return_expr.gen_macros(data, state));
|
||||
globals.extend(return_expr.gen_macros(data, state, map));
|
||||
}
|
||||
globals
|
||||
}
|
||||
}
|
||||
|
||||
impl mir::Statement {
|
||||
fn gen_macros(&mut self, data: &MacroPass, state: &mut MacroPassState) -> Vec<GlobalValue> {
|
||||
fn gen_macros(&mut self, data: &MacroPass, state: &mut MacroPassState, map: &MacroModuleMap) -> Vec<GlobalValue> {
|
||||
let mut globals = Vec::new();
|
||||
match &mut self.0 {
|
||||
mir::StmtKind::Let(.., expr) => {
|
||||
globals.extend(expr.gen_macros(data, state));
|
||||
globals.extend(expr.gen_macros(data, state, map));
|
||||
}
|
||||
mir::StmtKind::Set(lhs, rhs) => {
|
||||
globals.extend(lhs.gen_macros(data, state));
|
||||
globals.extend(rhs.gen_macros(data, state));
|
||||
globals.extend(lhs.gen_macros(data, state, map));
|
||||
globals.extend(rhs.gen_macros(data, state, map));
|
||||
}
|
||||
mir::StmtKind::Import(_) => {}
|
||||
mir::StmtKind::Expression(expr) => {
|
||||
globals.extend(expr.gen_macros(data, state));
|
||||
globals.extend(expr.gen_macros(data, state, map));
|
||||
}
|
||||
mir::StmtKind::While(WhileStatement { condition, block, .. }) => {
|
||||
globals.extend(condition.gen_macros(data, state));
|
||||
globals.extend(block.gen_macros(data, state));
|
||||
globals.extend(condition.gen_macros(data, state, map));
|
||||
globals.extend(block.gen_macros(data, state, map));
|
||||
}
|
||||
};
|
||||
globals
|
||||
@ -91,7 +114,7 @@ impl mir::Statement {
|
||||
}
|
||||
|
||||
impl mir::Expression {
|
||||
fn gen_macros(&mut self, data: &MacroPass, state: &mut MacroPassState) -> Vec<GlobalValue> {
|
||||
fn gen_macros(&mut self, data: &MacroPass, state: &mut MacroPassState, map: &MacroModuleMap) -> Vec<GlobalValue> {
|
||||
let mut globals = Vec::new();
|
||||
match &mut self.0 {
|
||||
mir::ExprKind::FunctionCall(function_call) => {
|
||||
@ -106,7 +129,14 @@ impl mir::Expression {
|
||||
}
|
||||
let (generated_globals, expr) = state.or_else(
|
||||
existing_macro
|
||||
.generate(&literals)
|
||||
.generate(
|
||||
map.get(&state.scope.module_id.unwrap()).unwrap(),
|
||||
&literals,
|
||||
format!(
|
||||
"macro.{}.{}.{}",
|
||||
function_call.name, self.1.range.start, self.1.range.end
|
||||
),
|
||||
)
|
||||
.map(|(globals, kind)| (globals, mir::Expression(kind, self.1))),
|
||||
(Vec::new(), self.clone()),
|
||||
self.1,
|
||||
@ -123,26 +153,26 @@ impl mir::Expression {
|
||||
}
|
||||
mir::ExprKind::Variable(_) => {}
|
||||
mir::ExprKind::Indexed(expression, _, expression1) => {
|
||||
globals.extend(expression.gen_macros(data, state));
|
||||
globals.extend(expression1.gen_macros(data, state));
|
||||
globals.extend(expression.gen_macros(data, state, map));
|
||||
globals.extend(expression1.gen_macros(data, state, map));
|
||||
}
|
||||
mir::ExprKind::Accessed(expression, ..) => {
|
||||
globals.extend(expression.gen_macros(data, state));
|
||||
globals.extend(expression.gen_macros(data, state, map));
|
||||
}
|
||||
mir::ExprKind::Array(expressions) => {
|
||||
for expression in expressions {
|
||||
globals.extend(expression.gen_macros(data, state));
|
||||
globals.extend(expression.gen_macros(data, state, map));
|
||||
}
|
||||
}
|
||||
mir::ExprKind::Struct(_, items) => {
|
||||
for item in items {
|
||||
globals.extend(item.1.gen_macros(data, state));
|
||||
globals.extend(item.1.gen_macros(data, state, map));
|
||||
}
|
||||
}
|
||||
mir::ExprKind::Literal(_) => {}
|
||||
mir::ExprKind::BinOp(_, expression, expression1, _) => {
|
||||
globals.extend(expression.gen_macros(data, state));
|
||||
globals.extend(expression1.gen_macros(data, state));
|
||||
globals.extend(expression.gen_macros(data, state, map));
|
||||
globals.extend(expression1.gen_macros(data, state, map));
|
||||
}
|
||||
mir::ExprKind::AssociatedFunctionCall(
|
||||
_,
|
||||
@ -151,27 +181,27 @@ impl mir::Expression {
|
||||
},
|
||||
) => {
|
||||
for expression in parameters {
|
||||
globals.extend(expression.gen_macros(data, state));
|
||||
globals.extend(expression.gen_macros(data, state, map));
|
||||
}
|
||||
}
|
||||
mir::ExprKind::If(IfExpression(cond, lhs, rhs)) => {
|
||||
globals.extend(cond.gen_macros(data, state));
|
||||
globals.extend(lhs.gen_macros(data, state));
|
||||
globals.extend(cond.gen_macros(data, state, map));
|
||||
globals.extend(lhs.gen_macros(data, state, map));
|
||||
if let Some(rhs) = rhs.as_mut() {
|
||||
globals.extend(rhs.gen_macros(data, state));
|
||||
globals.extend(rhs.gen_macros(data, state, map));
|
||||
}
|
||||
}
|
||||
mir::ExprKind::Block(block) => {
|
||||
globals.extend(block.gen_macros(data, state));
|
||||
globals.extend(block.gen_macros(data, state, map));
|
||||
}
|
||||
mir::ExprKind::Borrow(expression, _) => {
|
||||
globals.extend(expression.gen_macros(data, state));
|
||||
globals.extend(expression.gen_macros(data, state, map));
|
||||
}
|
||||
mir::ExprKind::Deref(expression) => {
|
||||
globals.extend(expression.gen_macros(data, state));
|
||||
globals.extend(expression.gen_macros(data, state, map));
|
||||
}
|
||||
mir::ExprKind::CastTo(expression, _) => {
|
||||
globals.extend(expression.gen_macros(data, state));
|
||||
globals.extend(expression.gen_macros(data, state, map));
|
||||
}
|
||||
mir::ExprKind::GlobalRef(..) => {}
|
||||
}
|
||||
@ -182,15 +212,20 @@ impl mir::Expression {
|
||||
pub fn form_macros() -> HashMap<String, Box<dyn MacroFunction>> {
|
||||
let mut macros: HashMap<String, Box<dyn MacroFunction>> = HashMap::new();
|
||||
|
||||
macros.insert("test_macro".to_owned(), Box::new(TestMacro));
|
||||
macros.insert("include_bytes".to_owned(), Box::new(IncludeBytes));
|
||||
|
||||
macros
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TestMacro;
|
||||
impl MacroFunction for TestMacro {
|
||||
fn generate<'ctx, 'a>(&self, literals: &[mir::Literal]) -> Result<(Vec<GlobalValue>, mir::ExprKind), ErrorKind> {
|
||||
pub struct IncludeBytes;
|
||||
impl MacroFunction for IncludeBytes {
|
||||
fn generate<'ctx, 'a>(
|
||||
&self,
|
||||
module: &MacroModule,
|
||||
literals: &[mir::Literal],
|
||||
global_name: String,
|
||||
) -> Result<(Vec<GlobalValue>, mir::ExprKind), ErrorKind> {
|
||||
if literals.len() != 1 {
|
||||
return Err(ErrorKind::InvalidAmountOfParams(literals.len() as u32, 1));
|
||||
}
|
||||
@ -202,6 +237,14 @@ impl MacroFunction for TestMacro {
|
||||
));
|
||||
};
|
||||
|
||||
let path = module
|
||||
.path
|
||||
.as_ref()
|
||||
.expect("Module has no path!")
|
||||
.parent()
|
||||
.expect("Module path has no parent!")
|
||||
.join(path);
|
||||
|
||||
let contents = match std::fs::read(path) {
|
||||
Ok(content) => content,
|
||||
Err(e) => return Err(ErrorKind::MacroExecutionError(format!("{}", e))),
|
||||
@ -214,7 +257,6 @@ impl MacroFunction for TestMacro {
|
||||
|
||||
let len = literals.len();
|
||||
|
||||
let global_name = "sometestglobalvalue".to_owned();
|
||||
let global = GlobalValue {
|
||||
name: global_name.clone(),
|
||||
kind: GlobalKind::Array(literals),
|
||||
@ -222,7 +264,10 @@ impl MacroFunction for TestMacro {
|
||||
|
||||
Ok((
|
||||
vec![global.clone()],
|
||||
mir::ExprKind::GlobalRef(global_name, TypeKind::U8),
|
||||
mir::ExprKind::GlobalRef(
|
||||
global_name,
|
||||
TypeKind::Borrow(Box::new(TypeKind::Array(Box::new(TypeKind::U8), len as u64)), false),
|
||||
),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -256,6 +256,16 @@ impl TypeKind {
|
||||
let other_cat = other.category();
|
||||
match (self, other) {
|
||||
(TypeKind::UserPtr(_), TypeKind::UserPtr(_)) => Ok(other.clone()),
|
||||
(TypeKind::Borrow(ty1, _), TypeKind::UserPtr(ty2)) => match *ty1.clone() {
|
||||
TypeKind::Array(ty1, _) => {
|
||||
if ty1 == *ty2 {
|
||||
Ok(other.clone())
|
||||
} else {
|
||||
Err(ErrorKind::NotCastableTo(self.clone(), other.clone()))
|
||||
}
|
||||
}
|
||||
_ => Err(ErrorKind::NotCastableTo(self.clone(), other.clone())),
|
||||
},
|
||||
(TypeKind::Char, TypeKind::U8) => Ok(other.clone()),
|
||||
(TypeKind::U8, TypeKind::Char) => Ok(other.clone()),
|
||||
_ => match (&self_cat, &other_cat) {
|
||||
|
Loading…
Reference in New Issue
Block a user