Skip to content

Commit

Permalink
[IR] starting semnatic analalsies
Browse files Browse the repository at this point in the history
  • Loading branch information
Cr0a3 committed Sep 7, 2024
1 parent 5205534 commit 37d3b7d
Show file tree
Hide file tree
Showing 6 changed files with 268 additions and 13 deletions.
5 changes: 3 additions & 2 deletions src/IR/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ impl Function {

let mut string = String::new();

string += &format!("define {} @{}({}) {{\n", self.ty.ret, self.name, {
string += &format!("define {} {} @{}({}) {{\n", self.linkage, self.ty.ret, self.name, {
let mut fmt = String::new();

for (name, metadata) in &self.ty.args {
Expand All @@ -158,8 +158,9 @@ impl Function {
/// Emits the Ir of the function into an colored string
pub fn dumpColored(&self, profile: ColorProfile) -> String {
if self.linkage == Linkage::Extern {
let string = format!("{} {} @{}( {})\n",
let string = format!("{} {} {} @{}( {})\n",
profile.markup("declare", ColorClass::Instr),
profile.markup(&format!("{}", self.linkage), ColorClass::Ty),
profile.markup(&self.ty.ret.to_string(), ColorClass::Ty),
profile.markup(&self.name, ColorClass::Name), {
let mut fmt = String::new();
Expand Down
84 changes: 83 additions & 1 deletion src/IR/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use lexer::Loc;

use crate::Support::{self, Colorize};

use super::Module;
use super::{Module, TypeMetadata};

/// Ygen-Ir lexing
pub mod lexer;
Expand Down Expand Up @@ -75,6 +75,42 @@ pub enum IrError {

/// A unkown type
UnkownType(lexer::Token),

/// Value defined twice
DefinedTwice {
/// the location
loc: Loc,
/// the name
name: String,
},

/// the given return type is different than the expected one from the function type
FuncWrongReturnTyoe {
/// the expected return type
expected: TypeMetadata,
/// the found type
found: TypeMetadata,
/// location
loc: Loc,
},

/// unkown thing
Unkown {
/// whats unkown (e.g: block)
what: String,
/// the "thingy"s name
name: String,
/// location
loc: Loc,
},

/// an extern function has an body
ExternFunWithBody {
/// the name of the function
name: String,
/// the location
loc: Loc,
}
}

impl Display for IrError {
Expand Down Expand Up @@ -187,6 +223,52 @@ impl Display for IrError {

fab.to_string()
}

IrError::DefinedTwice { loc, name } => {
let mut fab = Support::Error::new("defined twice", "", "", "");

fab.deactivateLocationDisplay();

fab.setCodeLine(loc.line_string.to_owned());
fab.addWhere(format!("{} was defined twice", name), loc.coloumn, loc.length);

fab.to_string()
}

IrError::FuncWrongReturnTyoe { expected, found, loc } => {
let mut fab = Support::Error::new("wrong return type", "", "", "");

fab.deactivateLocationDisplay();

fab.setCodeLine(loc.line_string.to_owned());

fab.addWhere(format!("encountered the wrong return type: {found} but expected: {expected}"), loc.coloumn, loc.length);

fab.to_string()
}

IrError::Unkown { what, name, loc } => {
let mut fab = Support::Error::new(format!("unkown {what}"), "", "", "col");

fab.deactivateLocationDisplay();

fab.setCodeLine(loc.line_string.to_owned());

fab.addWhere(format!("unkown {what}: {name}"), loc.coloumn, loc.length);

fab.to_string()
}

IrError::ExternFunWithBody { name, loc } => {
let mut fab = Support::Error::new("extern function has an body", "", "", "");

fab.deactivateLocationDisplay();

fab.setCodeLine(loc.line_string.to_owned());
fab.addWhere(format!("the func {name} is imported and has a body which isn't allowed"), loc.coloumn, loc.length);

fab.to_string()
}
})
}
}
Expand Down
32 changes: 27 additions & 5 deletions src/IR/parser/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use super::IrError;
#[derive(Debug, Clone, Eq)]
#[allow(missing_docs)]
pub struct IrInstr {
loc: Loc,
inst: Box<dyn Ir>,
pub(crate) loc: Loc,
pub(crate) inst: Box<dyn Ir>,
}

impl PartialEq for IrInstr {
Expand All @@ -23,8 +23,8 @@ impl PartialEq for IrInstr {
#[derive(Debug, Clone, PartialEq, Eq)]
#[allow(missing_docs)]
pub struct IrBlock {
loc: Loc,
body: Vec<IrInstr>,
pub(crate) loc: Loc,
pub(crate) body: Vec<IrInstr>,
}

/// An ir statement
Expand All @@ -39,6 +39,8 @@ pub enum IrStmt {
args: (HashMap<String, TypeMetadata>, /*unlim args*/bool),
body: HashMap<String, IrBlock>,
scope: Linkage,

location: Loc,
},
/// a constant
Const{
Expand Down Expand Up @@ -106,6 +108,7 @@ impl IrParser {
self.expect( TokenType::Func(String::new()) )?;

let tok = self.current_token()?;
let loc = tok.loc.to_owned();
if let TokenType::Func(func) = &tok.typ {
name = func.to_string();
} else { unreachable!() }
Expand Down Expand Up @@ -160,6 +163,8 @@ impl IrParser {
scope: Linkage::Extern,
args: (args, unlim),
ret: ret,

location: loc,
})
}

Expand All @@ -168,16 +173,31 @@ impl IrParser {
let mut body = HashMap::new();
let mut args = HashMap::new();

let mut link = Linkage::External;

self.expect( TokenType::Define )?;
self.input.pop_front(); // advance over define

let ret = self.parse_type()?;
self.input.pop_front();

let curr = self.current_token()?;

if let TokenType::Ident(ident) = &curr.typ {
link = match ident.as_str() {
"local" | "internal" | "private" => Linkage::Internal,
_ => Err(IrError::Unkown {
what: "linkage".to_owned(),
name: ident.to_owned(),
loc: curr.loc.clone()
})?
};
}

self.expect( TokenType::Func(String::new()) )?;

let tok = self.current_token()?;
let loc = tok.loc.to_owned();
if let TokenType::Func(func) = &tok.typ {
name = func.to_string();
} else { unreachable!() }
Expand Down Expand Up @@ -237,8 +257,10 @@ impl IrParser {
name: name,
body: body,
args: (args, false),
scope: Linkage::Extern,
scope: link,
ret: ret,

location: loc,
})
}

Expand Down
141 changes: 137 additions & 4 deletions src/IR/parser/semnatic.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,157 @@
use super::parser::IrStmt;
use std::collections::HashMap;

use crate::Obj::Linkage;
use crate::IR::{Const, FnTy, FunctionType, Type, TypeMetadata, Var};

use crate::prelude::ir::*;

use super::parser::{IrStmt, IrBlock};
use super::lexer::Loc;
use super::IrError;

/// semantic analaysiz for ir stmts
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct IrSemnatic<'a> {
input: &'a Vec<IrStmt>,

const_sigs: HashMap<String, Linkage>,
func_sigs: HashMap<String, (FunctionType, Linkage)>,
}

impl<'a> IrSemnatic<'a> {
/// Creates an new ir semnatic analyzizer
pub fn new(exprs: &'a Vec<IrStmt>) -> Self {
Self {
input: exprs,

const_sigs: HashMap::new(),
func_sigs: HashMap::new(),
}
}

/// verifys the input
pub fn verify(&mut self) -> Result<(), IrError> {
todo!();
for stmt in self.input {
match stmt {
IrStmt::Func { name, ret, args, body: _, scope, location } => self.add_func(name, *ret, args, scope, location)?,
IrStmt::Const { name, data: _, location, scope } => self.add_const(name, scope, location)?
}
}

for stmt in self.input {
match stmt {
IrStmt::Func { name, ret, args, body, scope, location } => self.analizye_func(name, *ret, args, body, *scope, location)?,
IrStmt::Const { name, data, location, scope } => self.analyize_const(name, data, location, *scope)?,
}
}

Ok(())
}

fn add_func(&mut self, name: &String, ret: TypeMetadata, args: &(HashMap<String, TypeMetadata>, bool), scope: &Linkage, loc: &Loc) -> Result<(), IrError> {
if self.func_sigs.contains_key(name) {
Err(IrError::DefinedTwice {
loc: loc.clone(),
name: name.to_owned()
})?
}

let mut fun_args = vec![];

for (_, arg) in &args.0 {
fun_args.push( *arg );
}

let ty = FnTy(fun_args, ret);

self.func_sigs.insert(name.to_owned(), (ty, *scope));

Ok(())
}

fn add_const(&mut self, name: &String, scope: &Linkage, loc: &Loc) -> Result<(), IrError> {
if self.func_sigs.contains_key(name) {
Err(IrError::DefinedTwice {
loc: loc.clone(),
name: name.to_owned()
})?
}

self.const_sigs.insert(name.to_owned(), *scope);
Ok(())
}

fn analizye_func(&mut self, name: &String, ret: TypeMetadata, args: &(HashMap<String, TypeMetadata>, bool), body: &HashMap<String, IrBlock>, scope: Linkage, loc: &Loc) -> Result<(), IrError> {
let mut vars = HashMap::new();

let mut blocks = vec![];

for (name, ty) in &args.0 {
vars.insert(name.to_owned(), *ty);
}

if Linkage::Extern == scope && body.len() > 0 {
Err(IrError::ExternFunWithBody {
name: name.to_owned(),
loc: loc.to_owned(),
})?
}

for (name, block) in body {
if blocks.contains(name) {
Err(IrError::DefinedTwice {
loc: block.loc.to_owned(),
name: name.to_owned()
})?
}

blocks.push(name.to_owned());

for node in &block.body {
let instr = &node.inst;
let loc = node.loc.to_owned();

let any = instr.as_any();

if let Some(node) = any.downcast_ref::<Return<Type>>() {
self.analiyze_ret_int(node, ret, loc)?;
} else if let Some(node) = any.downcast_ref::<Assign<Var, Const>>() {
self.analiyze_assign_const(node, loc)?;
}
}
}

Ok(())
}

fn analiyze_ret_int(&mut self, node: &Return<Type>, fsig: TypeMetadata, loc: Loc) -> Result<(), IrError> {
let ret: TypeMetadata = node.inner1.into();

if ret != fsig {
Err(IrError::FuncWrongReturnTyoe {
expected: fsig,
found: ret,
loc: loc,
})?
}

Ok(())
}

fn analiyze_assign_const(&mut self, node: &Assign<Var, Const>, loc: Loc) -> Result<(), IrError> {
let name = &node.inner2.name;
if !self.const_sigs.contains_key(name) {
Err(IrError::Unkown {
what: "const".to_owned(),
loc: loc,
name: name.to_owned(),
})?
}

Ok(())
}

//Ok(())
fn analyize_const(&mut self, _: &String, _: &Vec<u8>, _: &Loc, _: Linkage) -> Result<(), IrError> {
Ok(()) // what can go wrong on constants?
}
}
}
Loading

0 comments on commit 37d3b7d

Please sign in to comment.