Skip to content

Commit

Permalink
🚧 WIP
Browse files Browse the repository at this point in the history
semver: chore
  • Loading branch information
Somfic committed Nov 15, 2024
1 parent 000d039 commit 152b406
Show file tree
Hide file tree
Showing 10 changed files with 325 additions and 427 deletions.
64 changes: 26 additions & 38 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ description = "The 'som' programming language"

[dependencies]
miette = { version = "7.2.0", features = ["fancy", "syntect-highlighter"] }
thiserror = "2.0.3"
owo-colors = "4.1.0"
pretty_assertions = "1.4.1"
regex = "1.10"
175 changes: 175 additions & 0 deletions src/generator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
use std::fmt::format;

use crate::parser::ast::{
Expression, ExpressionValue, Primitive, Statement, StatementValue, Symbol,
};

pub struct CodeGenerator<'de> {
indent_level: usize,
symbol: &'de Symbol<'de>,
}

impl<'de> CodeGenerator<'de> {
// create a new builder with no indentation
pub fn new(symbol: &'de Symbol<'de>) -> Self {
Self {
indent_level: 0,
symbol,
}
}

// compile the entire symbol
pub fn compile(&mut self) -> String {
match self.symbol {
Symbol::Statement(statement) => self.compile_statement(statement),
Symbol::Expression(expression) => self.compile_expression(expression),
}
}

// increase the indentation level
fn increase_indent(&mut self) {
self.indent_level += 1;
}

// decrease the indentation level
fn decrease_indent(&mut self) {
if self.indent_level > 0 {
self.indent_level -= 1;
}
}

// get the current indentation as a string of spaces
fn current_indent(&self) -> String {
" ".repeat(self.indent_level) // adjust spaces per level as needed
}

// compile a block of statements, maintaining indentation
fn compile_block(&mut self, statements: &[Statement]) -> String {
let mut code = String::new();
self.increase_indent();
for stmt in statements {
code.push_str(&format!(
"{}{}\n",
self.current_indent(),
self.compile_statement(stmt)
));
}
self.decrease_indent();
code
}

// compile an individual statement
fn compile_statement(&mut self, stmt: &Statement) -> String {
match &stmt.value {
StatementValue::Assignment { name, value } => {
format!("var {} = {};", name, self.compile_expression(value))
}
StatementValue::Return(expression) => {
format!("return {};", self.compile_expression(expression))
}
StatementValue::Block(block_statements) => {
let mut block_code = String::from("{\n");
block_code.push_str(&self.compile_block(block_statements));
block_code.push_str(&format!("{}}}", self.current_indent()));
block_code
}
StatementValue::Function { header, body } => {
let mut code = format!("function {}(", header.name);
for (i, parameter) in header.parameters.iter().enumerate() {
if i > 0 {
code.push_str(", ");
}
code.push_str(&parameter.name);
}

code.push_str(") {\n");
code.push_str(&self.compile_expression(body));
code.push_str(&format!("\n{}}}", self.current_indent()));

code
}
StatementValue::Expression(expression) => {
format!("{}", self.compile_expression(expression))
}
StatementValue::Conditional {
condition,
truthy,
falsy,
} => {
let mut code = format!("if {} {{\n", self.compile_expression(condition));
self.increase_indent();
code.push_str(&self.compile_statement(truthy));
self.decrease_indent();
code.push_str(&format!("\n{}}}", self.current_indent()));
if let Some(falsy) = falsy {
code.push_str(" else {\n");
self.increase_indent();
code.push_str(&self.compile_statement(falsy));
self.decrease_indent();
code.push_str(&format!("\n{}}}", self.current_indent()));
}
code
}
_ => {
println!("{:?}", stmt);
todo!("handle more statement types")
}
}
}

// compile an expression (placeholder for your full expression handling)
fn compile_expression(&mut self, expr: &Expression) -> String {
match &expr.value {
ExpressionValue::Primitive(primitive) => primitive.to_string(),
ExpressionValue::Binary {
operator,
left,
right,
} => {
format!(
"({} {} {})",
self.compile_expression(left),
operator,
self.compile_expression(right)
)
}
ExpressionValue::Group(inner) => self.compile_expression(inner).to_string(),
ExpressionValue::Block {
statements,
return_value,
} => {
let mut code = String::new();
code.push_str(&self.compile_block(statements));
self.increase_indent();

if let ExpressionValue::Primitive(Primitive::Unit) = return_value.value {
} else {
code.push_str(&format!(
"{}return {};",
self.current_indent(),
self.compile_expression(return_value)
));
}

self.decrease_indent();
code
}
ExpressionValue::Conditional {
condition,
truthy,
falsy,
} => {
format!(
"{} ? {} : {}",
self.compile_expression(condition),
self.compile_expression(truthy),
self.compile_expression(falsy)
)
}
_ => {
println!("{:?}", expr);
todo!("handle more expression types")
}
}
}
}
27 changes: 8 additions & 19 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
use generator::CodeGenerator;
use lexer::{Lexer, TokenKind};
use owo_colors::{Style, Styled};
use parser::{
ast::{Expression, ExpressionValue, Statement},
Parser,
};
use passer::{typing::Typing, Passer};
use std::vec;

pub mod generator;
pub mod lexer;
pub mod parser;
pub mod passer;
pub mod typing;

const INPUT: &str = "
fn main() {
let string = \"Hello, world!\";
return 12;
let cum = 12;
{
let string = \"Hello, world!\";
return 12;
};
let abc = 12;
1 + 1 if cum > 12 else 2
}
";

Expand All @@ -47,16 +42,10 @@ fn main() {
}
};

let typing_pass = passer::typing::TypingPasser::pass(&symbol).unwrap();
let typing_pass = typing_pass.combine(passer::unused::UnusedPass::pass(&symbol).unwrap());
let mut generator = CodeGenerator::new(&symbol);
let code = generator.compile();

for note in typing_pass.non_critical {
println!("{:?}", note.with_source_code(INPUT));
}

for note in typing_pass.critical {
println!("{:?}", note.with_source_code(INPUT));
}
println!("{}", code);
}

struct SomHighlighter {}
Expand Down
5 changes: 2 additions & 3 deletions src/parser/ast.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::{borrow::Cow, fmt::Display};

use miette::SourceSpan;
use std::{borrow::Cow, fmt::Display};

#[derive(Debug, Clone)]
pub enum Symbol<'de> {
Expand Down Expand Up @@ -108,7 +107,7 @@ impl Display for Primitive<'_> {
Primitive::Identifier(value) => write!(f, "{}", value),
Primitive::Character(value) => write!(f, "{}", value),
Primitive::Boolean(value) => write!(f, "{}", value),
Primitive::Unit => write!(f, "nothing"),
Primitive::Unit => write!(f, "§"),
}
}
}
Expand Down
Loading

0 comments on commit 152b406

Please sign in to comment.