More work on UIR
This commit is contained in:
parent
4480a1973a
commit
2607722686
|
@ -4,8 +4,10 @@
|
|||
//! simplifies the complexity of the syntax tree, and is used to perform type inference, at which
|
||||
//! point it is translated into typed IR.
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
use crate::{
|
||||
syntax::{self, Identifier, SyntaxTree},
|
||||
syntax::{self, Identifier, Literal, SyntaxTree},
|
||||
typeck::Type,
|
||||
};
|
||||
|
||||
|
@ -143,6 +145,19 @@ enum Location {
|
|||
|
||||
/// A compiler-generated temporary location.
|
||||
Temporary(u64),
|
||||
|
||||
/// A constant value.
|
||||
Literal(Literal),
|
||||
}
|
||||
|
||||
impl Display for Location {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Location::Named(id) => write!(f, "n`{}`", id),
|
||||
Location::Temporary(t) => write!(f, "t`{}`", t),
|
||||
Location::Literal(l) => write!(f, "c`{}`", l),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a program's abstract syntax tree into untyped IR code.
|
||||
|
@ -204,7 +219,13 @@ fn convert_fn(
|
|||
mut arguments: Vec<syntax::Pattern>,
|
||||
definition: syntax::Expr,
|
||||
) -> Vec<Instruction> {
|
||||
if arguments.len() > 1 {
|
||||
if arguments.is_empty() {
|
||||
let ret_loc = temporary(counter);
|
||||
eval_expr(counter, definition, &ret_loc)
|
||||
.into_iter()
|
||||
.chain(std::iter::once(Instruction::Return { target: ret_loc }))
|
||||
.collect()
|
||||
} else {
|
||||
let first = arguments.remove(0);
|
||||
|
||||
let lambda_loc = temporary(counter);
|
||||
|
@ -220,12 +241,6 @@ fn convert_fn(
|
|||
},
|
||||
Instruction::Return { target: lambda_loc },
|
||||
]
|
||||
} else {
|
||||
let ret_loc = temporary(counter);
|
||||
eval_expr(counter, definition, &ret_loc)
|
||||
.into_iter()
|
||||
.chain(std::iter::once(Instruction::Return { target: ret_loc }))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -271,11 +286,6 @@ fn bind_pattern(counter: &mut u64, p: syntax::Pattern, l: &Location) -> Vec<Inst
|
|||
/// Emits intructions that evaluate the expression `e`, then place the result in location `l`.
|
||||
fn eval_expr(counter: &mut u64, e: syntax::Expr, l: &Location) -> Vec<Instruction> {
|
||||
match e {
|
||||
syntax::Expr::UnaryOp {
|
||||
kind,
|
||||
val,
|
||||
translation,
|
||||
} => todo!(),
|
||||
syntax::Expr::BinaryOp {
|
||||
kind,
|
||||
left,
|
||||
|
@ -315,7 +325,13 @@ fn eval_expr(counter: &mut u64, e: syntax::Expr, l: &Location) -> Vec<Instructio
|
|||
}))
|
||||
.collect()
|
||||
}
|
||||
syntax::Expr::VariableReference(_) => todo!(),
|
||||
syntax::Expr::Literal(_) => todo!(),
|
||||
syntax::Expr::VariableReference(name) => vec![Instruction::Collect {
|
||||
target: l.clone(),
|
||||
source: vec![Location::Named(name)],
|
||||
}],
|
||||
syntax::Expr::Literal(lit) => vec![Instruction::Collect {
|
||||
target: l.clone(),
|
||||
source: vec![Location::Literal(lit)],
|
||||
}],
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ use std::{error::Error, fmt::Display, process::exit, str::FromStr};
|
|||
|
||||
use clap::Parser;
|
||||
use drimc_rs::{
|
||||
ir_untyped::ast_to_untyped_ir,
|
||||
parser::{parser, ParserError, ParserMeta},
|
||||
typeck::typeck, ir_untyped::ast_to_untyped_ir,
|
||||
};
|
||||
|
||||
/// Optimization levels.
|
||||
|
@ -98,6 +98,10 @@ impl FromStr for Optimization {
|
|||
/// Targets for compiling to.
|
||||
#[derive(Debug)]
|
||||
enum Target {
|
||||
// -------------------- IR generation --------------------
|
||||
/// Generate untyped intermediate representation (UIR) code.
|
||||
UIR,
|
||||
|
||||
// -------------------- C generation --------------------
|
||||
|
||||
// Highest priority codegen, since it allows us to compile to the vast majority of possible
|
||||
|
@ -138,25 +142,26 @@ enum Target {
|
|||
Wasm,
|
||||
|
||||
// -------------------- Other language generation --------------------
|
||||
/// Directly generate Lua code.
|
||||
|
||||
// Medium-priority codegen, since Lua is the only type of code that runs in e.g. plugins and
|
||||
// scripts in some software, and it is difficult to generate efficient Lua without direct
|
||||
// support from the compiler.
|
||||
/// Directly generate Lua code.
|
||||
Lua,
|
||||
|
||||
/// Directly generate Python code.
|
||||
// Low-priority codegen; the same situation as Lua, but situations that require Python code with
|
||||
// no alternatives are much less common than situations that require Lua code with no
|
||||
// alternatives.
|
||||
/// Directly generate Python code.
|
||||
Python,
|
||||
|
||||
/// Directly generate Go code.
|
||||
// Extremely low-priority codegen; almost no valid use cases.
|
||||
/// Directly generate Go code.
|
||||
Go,
|
||||
|
||||
/// Directly generate Ada code.
|
||||
// Currently zero-priority codegen; no valid use cases whatsoever as far as I (Alex) can
|
||||
// determine.
|
||||
/// Directly generate Ada code.
|
||||
Ada,
|
||||
}
|
||||
|
||||
|
@ -166,6 +171,7 @@ impl Display for Target {
|
|||
f,
|
||||
"{}",
|
||||
match self {
|
||||
Target::UIR => "uir",
|
||||
Target::CSource => "c",
|
||||
Target::Assembly => "asm",
|
||||
Target::ObjectFile => "obj",
|
||||
|
@ -190,6 +196,7 @@ impl FromStr for Target {
|
|||
use Target::*;
|
||||
|
||||
let targets = [
|
||||
("uir", "Untyped intermediate representation.", UIR),
|
||||
("c", "C source code.", CSource),
|
||||
("asm", "Assembly code.", Assembly),
|
||||
("obj", "Object file.", ObjectFile),
|
||||
|
|
|
@ -379,9 +379,7 @@ fn parse_expression<'a>(
|
|||
.unwrap()
|
||||
});
|
||||
|
||||
let unary = parse_unary(m, application);
|
||||
|
||||
let binary = (0..=10).rev().fold(unary.boxed(), |p, precedence| {
|
||||
let binary = (0..=10).rev().fold(application.boxed(), |p, precedence| {
|
||||
parse_binary(m, precedence, p).boxed()
|
||||
});
|
||||
|
||||
|
@ -389,22 +387,6 @@ fn parse_expression<'a>(
|
|||
})
|
||||
}
|
||||
|
||||
fn parse_unary(
|
||||
_m: &ParserMeta,
|
||||
base: impl Parser<char, Expr, Error = Simple<char>> + Clone,
|
||||
) -> impl Parser<char, Expr, Error = Simple<char>> + Clone {
|
||||
pad(just("-").to("-"))
|
||||
.repeated()
|
||||
.then(base)
|
||||
.map(|(ops, exp)| {
|
||||
ops.into_iter().fold(exp, |exp, op| Expr::UnaryOp {
|
||||
kind: op.to_string(),
|
||||
val: Box::new(exp),
|
||||
translation: "negate".to_string(),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_binary<'a>(
|
||||
m: &'a ParserMeta,
|
||||
prec: u32,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
//! Syntax tree for Drim code.
|
||||
|
||||
use std::fmt::Display;
|
||||
|
||||
use num_bigint::BigUint;
|
||||
|
||||
/// A concrete syntax tree. This represents the full content of a Drim program, including all
|
||||
|
@ -90,18 +92,6 @@ pub struct TypeConstructor {
|
|||
/// The different kinds of expressions.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Expr {
|
||||
/// Unary operators, e.g., `-5`.
|
||||
UnaryOp {
|
||||
/// The text of the operator.
|
||||
kind: String,
|
||||
|
||||
/// The value being operated upon.
|
||||
val: Box<Expr>,
|
||||
|
||||
/// The function that the unary operator translates to.
|
||||
translation: String,
|
||||
},
|
||||
|
||||
/// Binary operators, e.g., `5 + 5`.
|
||||
BinaryOp {
|
||||
/// The text of the operator.
|
||||
|
@ -258,6 +248,18 @@ pub struct Identifier {
|
|||
pub elems: Vec<String>,
|
||||
}
|
||||
|
||||
impl Display for Identifier {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
for (n, e) in self.elems.iter().enumerate() {
|
||||
if n != 0 {
|
||||
write!(f, "::")?;
|
||||
}
|
||||
write!(f, "{}", e)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Literal values included in source code.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Literal {
|
||||
|
@ -270,3 +272,13 @@ pub enum Literal {
|
|||
/// `123.456`
|
||||
Float(f64),
|
||||
}
|
||||
|
||||
impl Display for Literal {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Literal::String(s) => write!(f, "{}", s),
|
||||
Literal::Integer(i) => write!(f, "{}", i),
|
||||
Literal::Float(fl) => write!(f, "{}", fl),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
// IR Test
|
||||
|
||||
def nul (a, b) = ();
|
||||
def nul (a, b) = sin a;
|
||||
|
|
Loading…
Reference in a new issue