split std

This commit is contained in:
2026-07-01 14:43:39 +02:00
parent 3a4a499cf6
commit bc4e09805b
53 changed files with 1415 additions and 1279 deletions

View File

@@ -147,8 +147,8 @@ _builtin_cvttsd2si:
cvttsd2si rax, xmm0
ret
.section .text._builtin_f64_to_float
_builtin_f64_to_float:
.section .text._builtin_f64_to_f32
_builtin_f64_to_f32:
cvtsd2ss xmm0, xmm0
movd eax, xmm0
ret
@@ -648,10 +648,10 @@ _builtin_environ:
emit!(&mut self.output, " lea rax, [rip + {}]", label);
}
TokenType::True => {
TokenType::KeywordTrue => {
emit!(&mut self.output, " mov rax, 1");
}
TokenType::False => {
TokenType::KeywordFalse => {
emit!(&mut self.output, " mov rax, 0");
}
_ => unreachable!(),

View File

@@ -5,6 +5,7 @@ mod tokenizer;
mod typechecker;
use std::{
collections::HashSet,
fs,
path::Path,
process::{self, Command},
@@ -27,8 +28,8 @@ fn compile_file(args: Args) -> Result<(), ZernError> {
let filename = Path::new(&args.path).file_name().unwrap().to_str().unwrap();
let mut tokenizer = tokenizer::Tokenizer::new(filename.to_owned(), source);
tokenizer.include_file("std/std.zr".into())?;
let mut included_paths = HashSet::new();
let tokenizer = tokenizer::Tokenizer::new(filename.to_owned(), source, &mut included_paths);
let parser = parser::Parser::new(tokenizer.tokenize()?);
let statements = parser.parse()?;

View File

@@ -665,8 +665,8 @@ impl Parser {
TokenType::FloatLiteral,
TokenType::CharLiteral,
TokenType::StringLiteral,
TokenType::True,
TokenType::False,
TokenType::KeywordTrue,
TokenType::KeywordFalse,
]) {
Ok(Expr::new(ExprKind::Literal(self.previous().clone())))
} else if self.match_token(&[TokenType::LeftParen]) {

View File

@@ -58,8 +58,8 @@ impl SymbolTable {
("_builtin_cvtsi2sd".into(), FnType::new("f64", vec!["i64"])),
("_builtin_cvttsd2si".into(), FnType::new("i64", vec!["f64"])),
(
"_builtin_f64_to_float".into(),
FnType::new("i64", vec!["f64"]),
"_builtin_f64_to_f32".into(),
FnType::new("any", vec!["f64"]),
),
("_builtin_syscall".into(), FnType::new_variadic("i64")),
("_builtin_environ".into(), FnType::new("ptr", vec![])),

View File

@@ -1,4 +1,9 @@
use std::{cmp::Ordering, fmt, fs, path::Path};
use std::{
cmp::Ordering,
collections::HashSet,
fmt, fs,
path::{Path, PathBuf},
};
#[derive(Debug, Clone, PartialEq)]
pub enum TokenType {
@@ -40,8 +45,6 @@ pub enum TokenType {
CharLiteral,
IntLiteral,
FloatLiteral,
True,
False,
KeywordConst,
KeywordIf,
@@ -58,6 +61,8 @@ pub enum TokenType {
KeywordStruct,
KeywordNew,
KeywordAs,
KeywordTrue,
KeywordFalse,
Indent,
Dedent,
@@ -109,7 +114,7 @@ pub struct Token {
pub loc: Loc,
}
pub struct Tokenizer {
pub struct Tokenizer<'a> {
source: Vec<char>,
tokens: Vec<Token>,
indent_stack: Vec<usize>,
@@ -117,10 +122,15 @@ pub struct Tokenizer {
start: usize,
current: usize,
loc: Loc,
included_paths: &'a mut HashSet<PathBuf>,
}
impl Tokenizer {
pub fn new(filename: String, source: String) -> Tokenizer {
impl<'a> Tokenizer<'a> {
pub fn new(
filename: String,
source: String,
included_paths: &'a mut HashSet<PathBuf>,
) -> Tokenizer<'a> {
Tokenizer {
source: source.chars().collect(),
tokens: vec![],
@@ -133,6 +143,7 @@ impl Tokenizer {
line: 1,
column: 1,
},
included_paths,
}
}
@@ -357,6 +368,9 @@ impl Tokenizer {
self.advance();
}
} else {
if self.source[self.current - 1] == '0' && self.peek().is_ascii_digit() {
return error!(self.loc, "octal literals are not allowed");
}
while self.peek().is_ascii_digit() {
self.advance();
}
@@ -406,8 +420,8 @@ impl Tokenizer {
"struct" => TokenType::KeywordStruct,
"new" => TokenType::KeywordNew,
"as" => TokenType::KeywordAs,
"true" => TokenType::True,
"false" => TokenType::False,
"true" => TokenType::KeywordTrue,
"false" => TokenType::KeywordFalse,
_ => TokenType::Identifier,
})
}
@@ -437,8 +451,18 @@ impl Tokenizer {
self.include_file(path)
}
// TODO: circular includes lead to "fatal runtime error: stack overflow, aborting"
pub fn include_file(&mut self, path: String) -> Result<(), ZernError> {
fn include_file(&mut self, path: String) -> Result<(), ZernError> {
let canonical = match fs::canonicalize(&path) {
Ok(p) => p,
Err(e) => {
return error!(self.loc, format!("failed to resolve {}: {}", path, e));
}
};
if !self.included_paths.insert(canonical) {
return Ok(());
}
let source = match fs::read_to_string(&path) {
Ok(x) => x,
Err(_) => {
@@ -448,7 +472,7 @@ impl Tokenizer {
let filename = Path::new(&path).file_name().unwrap().to_str().unwrap();
let tokenizer = Tokenizer::new(filename.to_owned(), source);
let tokenizer = Tokenizer::new(filename.to_owned(), source, &mut *self.included_paths);
self.tokens.extend(tokenizer.tokenize()?);
self.tokens.pop(); // remove inner Eof

View File

@@ -428,8 +428,8 @@ impl<'a> TypeChecker<'a> {
TokenType::FloatLiteral => Ok("f64".into()),
TokenType::CharLiteral => Ok("u8".into()),
TokenType::StringLiteral => Ok("str".into()),
TokenType::True => Ok("bool".into()),
TokenType::False => Ok("bool".into()),
TokenType::KeywordTrue => Ok("bool".into()),
TokenType::KeywordFalse => Ok("bool".into()),
_ => unreachable!(),
},
ExprKind::Unary { op, right } => {