Browse Source

begin refactoring vire

master
Alison Watson 2 years ago
parent
commit
31be81738b
  1. 6
      source/framework/ffi.rs
  2. 13
      source/framework/vire.rs
  3. 100
      source/framework/vire/compiler.rs
  4. 107
      source/framework/vire/parser.rs
  5. 7
      source/framework/vire/parser/tki.rs
  6. 130
      source/framework/vire/parser/tok.rs
  7. 12
      source/main_test/entry.rs

6
source/framework/ffi.rs

@ -17,6 +17,12 @@ pub fn cstr_from_slice(s: &[u8]) -> Option<&str> {
std::str::from_utf8(s).ok()
}
/// Converts a C string to a `&'static str`.
///
/// # Safety
///
/// This function is unsafe because it reads from a pointer. This
/// should not cause any undefined behaviour in any case.
#[inline]
pub unsafe fn cstr_from_ptr(s: Nts) -> Option<&'static str> {
CStr::from_ptr(s).to_str().ok()

13
source/framework/vire.rs

@ -1,17 +1,4 @@
pub mod compiler;
pub mod parser;
pub type Number = i64;
#[derive(Debug)]
pub enum Datum {
Null,
Bool(bool),
Char(char),
Numb(Number),
Strn(String),
Symb(String),
Cons(Box<Datum>, Box<Datum>),
}
// EOF

100
source/framework/vire/compiler.rs

@ -6,24 +6,85 @@ pub(self) use llvm_sys::{
core::*, execution_engine::*, prelude::*, target::*, target_machine::*,
};
pub(self) type DeclResult = (ffi::Nts, LLVMTypeRef, *mut std::ffi::c_void);
use super::parser::Datum;
type DeclFunc = unsafe fn(LLVMContextRef) -> DeclResult;
pub(self) type DeclResult = (ffi::Nts, LLVMTypeRef, *mut std::ffi::c_void);
#[derive(Error, Debug)]
pub enum Error {
#[error("Couldn't initialize JIT: {0}")]
JitInit(String),
#[error("Invalid syntax")]
Syntax,
}
pub struct Context {
contx: LLVMContextRef,
modul: LLVMModuleRef,
build: LLVMBuilderRef,
engin: LLVMExecutionEngineRef,
}
const DEF_FUNCTIONS: &[DeclFunc] = &[
nat::c_addi,
nat::c_subi,
nat::c_muli,
nat::c_divi,
nat::c_remi,
nat::c_dbgi,
];
impl Context {
/*
pub fn compile(&self, datum: Datum) -> Result<(), Error> {
match datum {
//Datum::Null,
//Datum::Bool(bool),
//Datum::Char(char),
//Datum::Numb(i64),
//Datum::Strn(String),
//Datum::Symb(String),
Datum::Cons { cdr, car } => {
// function call
}
_ => {
// compiles to no code
Ok(())
}
}
Ok(())
}
*/
pub fn new() -> Result<Self, Error> {
const DEF_FUNCTIONS: &[unsafe fn(LLVMContextRef) -> DeclResult] = &[
nat::c_addi,
nat::c_subi,
nat::c_muli,
nat::c_divi,
nat::c_remi,
nat::c_dbgi,
];
unsafe {
init_llvm();
let contx = LLVMContextCreate();
let modul = LLVMModuleCreateWithNameInContext(c_str!("test"), contx);
let build = LLVMCreateBuilderInContext(contx);
let engin = jit_engine(modul)?;
for decl in DEF_FUNCTIONS.iter() {
let (name, ftyp, fdef) = decl(contx);
let func = LLVMAddFunction(modul, name, ftyp);
LLVMAddGlobalMapping(engin, func, fdef);
}
Ok(Self { contx, modul, build, engin })
}
}
}
impl Drop for Context {
fn drop(&mut self) {
unsafe {
LLVMDisposeExecutionEngine(self.engin);
LLVMDisposeBuilder(self.build);
LLVMContextDispose(self.contx);
}
}
}
unsafe fn jit_engine(
modul: LLVMModuleRef,
@ -67,23 +128,4 @@ unsafe fn init_llvm() {
});
}
pub fn compile_context() -> Result<(), Error> {
unsafe {
init_llvm();
let contx = LLVMContextCreate();
let modul = LLVMModuleCreateWithNameInContext(c_str!("test"), contx);
let build = LLVMCreateBuilderInContext(contx);
let engin = jit_engine(modul)?;
for decl in DEF_FUNCTIONS.iter() {
let (name, ftyp, fdef) = decl(contx);
let func = LLVMAddFunction(modul, name, ftyp);
LLVMAddGlobalMapping(engin, func, fdef);
}
Ok(())
}
}
// EOF

107
source/framework/vire/parser.rs

@ -1,64 +1,79 @@
pub mod token;
pub mod tokeniter;
pub mod tki;
pub mod tok;
use self::{
token::{Data, Token, Type},
tokeniter::{Err, TokenIter},
tki::{Err, TokenIter},
tok::{Data, Token, Type::*},
};
use super::Datum;
fn abbreviation(tki: &mut TokenIter, name: &str) -> Result<Datum, Err> {
let lft = Datum::Symb(name.to_owned());
let mid = parse_datum(tki)?;
let rgt = Datum::Cons(Box::new(mid), Box::new(Datum::Null));
Ok(Datum::Cons(Box::new(lft), Box::new(rgt)))
#[derive(Debug)]
pub enum Datum {
Null,
Bool(bool),
Char(char),
Numb(i64),
Strn(String),
Symb(String),
Cons { cdr: Box<Datum>, car: Box<Datum> },
}
fn list(tki: &mut TokenIter, end: Type) -> Result<Datum, Err> {
let mut data_v = Vec::new();
let mut datum = Datum::Null;
impl Datum {
pub fn parse(tki: &mut TokenIter) -> Result<Self, Err> {
match tki.err_next()? {
// atoms
Token { typ: Bool, dat: Data::Bool(b), .. } => Ok(Self::Bool(b)),
Token { typ: Char, dat: Data::Char(c), .. } => Ok(Self::Char(c)),
Token { typ: Numb, dat: Data::Numb(n), .. } => Ok(Self::Numb(n)),
Token { typ: Strn, dat: Data::Strn(s), .. } => Ok(Self::Strn(s)),
Token { typ: Symb, dat: Data::Strn(s), .. } => Ok(Self::Symb(s)),
while !tki.drop(end)? {
if tki.drop(Type::Peri)? {
datum = parse_datum(tki)?;
tki.expect(end)?;
break;
} else {
data_v.push(parse_datum(tki)?);
// lists
Token { typ: Br1O, .. } => Self::list(tki, Br1C),
Token { typ: Br3O, .. } => Self::list(tki, Br3C),
// abbreviations
Token { typ: QQuo, .. } => Self::abbrev(tki, "quasiquote"),
Token { typ: QSyn, .. } => Self::abbrev(tki, "quasisyntax"),
Token { typ: Quot, .. } => Self::abbrev(tki, "quote"),
Token { typ: Synt, .. } => Self::abbrev(tki, "syntax"),
Token { typ: UnQS, .. } => Self::abbrev(tki, "unquote-splicing"),
Token { typ: UnQu, .. } => Self::abbrev(tki, "unquote"),
Token { typ: UnSS, .. } => Self::abbrev(tki, "unsyntax-splicing"),
Token { typ: UnSy, .. } => Self::abbrev(tki, "unsyntax"),
Token { typ, pos, .. } => Err(Err::Unexpected(typ, pos)),
}
}
for lhs in data_v.into_iter().rev() {
datum = Datum::Cons(Box::new(lhs), Box::new(datum));
fn abbrev(tki: &mut TokenIter, name: &str) -> Result<Self, Err> {
let cdr = {
let cdr = Box::new(Self::Null);
let car = Box::new(Self::parse(tki)?);
Box::new(Self::Cons { cdr, car })
};
let car = Box::new(Self::Symb(name.to_owned()));
Ok(Self::Cons { cdr, car })
}
Ok(datum)
}
pub fn parse_datum(tki: &mut TokenIter) -> Result<Datum, Err> {
match tki.err_next()? {
// atoms
Token { typ: Type::Bool, dat: Data::Bool(b), .. } => Ok(Datum::Bool(b)),
Token { typ: Type::Char, dat: Data::Char(c), .. } => Ok(Datum::Char(c)),
Token { typ: Type::Numb, dat: Data::Numb(n), .. } => Ok(Datum::Numb(n)),
Token { typ: Type::Strn, dat: Data::Strn(s), .. } => Ok(Datum::Strn(s)),
Token { typ: Type::Symb, dat: Data::Strn(s), .. } => Ok(Datum::Symb(s)),
fn list(tki: &mut TokenIter, end: tok::Type) -> Result<Self, Err> {
let mut data_v = Vec::new();
let mut car = Self::Null;
// lists
Token { typ: Type::Br1O, .. } => list(tki, Type::Br1C),
Token { typ: Type::Br3O, .. } => list(tki, Type::Br3C),
while !tki.drop(end)? {
if tki.drop(Peri)? {
car = Self::parse(tki)?;
tki.expect(end)?;
break;
} else {
data_v.push(Self::parse(tki)?);
}
}
// abbreviations
Token { typ: Type::QQuo, .. } => abbreviation(tki, "quasiquote"),
Token { typ: Type::QSyn, .. } => abbreviation(tki, "quasisyntax"),
Token { typ: Type::Quot, .. } => abbreviation(tki, "quote"),
Token { typ: Type::Synt, .. } => abbreviation(tki, "syntax"),
Token { typ: Type::UnQS, .. } => abbreviation(tki, "unquote-splicing"),
Token { typ: Type::UnQu, .. } => abbreviation(tki, "unquote"),
Token { typ: Type::UnSS, .. } => abbreviation(tki, "unsyntax-splicing"),
Token { typ: Type::UnSy, .. } => abbreviation(tki, "unsyntax"),
for cdr in data_v.into_iter() {
car = Self::Cons { cdr: Box::new(cdr), car: Box::new(car) };
}
Token { typ, pos, .. } => Err(Err::Unexpected(typ, pos)),
Ok(car)
}
}

7
source/framework/vire/parser/tokeniter.rs → source/framework/vire/parser/tki.rs

@ -1,4 +1,4 @@
use super::token::{Token, Type};
use super::tok::{self, Token, Type};
use crate::data::text::Position;
use std::{iter::Peekable, vec};
@ -12,6 +12,7 @@ pub enum Err {
Expected(Type, Type, Position),
}
#[derive(Debug)]
pub struct TokenIter {
it: Peekable<vec::IntoIter<Token>>,
}
@ -21,6 +22,10 @@ impl TokenIter {
Self { it: v.into_iter().peekable() }
}
pub fn from_data(name: &str, data: &str) -> Result<Self, tok::Err> {
Ok(Self::new(Token::read_all(name, data)?))
}
pub fn drop(&mut self, typ: Type) -> Result<bool, Err> {
let tk = self.err_peek()?;
if tk.typ == typ {

130
source/framework/vire/parser/token.rs → source/framework/vire/parser/tok.rs

@ -1,7 +1,4 @@
use crate::{
data::text::{self, PosReader, Position},
vire::Number,
};
use crate::data::text::{self, PosReader, Position};
use std::fmt;
#[derive(Error, Debug)]
@ -54,7 +51,7 @@ pub enum Data {
Bool(bool),
Char(char),
None,
Numb(Number),
Numb(i64),
Strn(String),
}
@ -189,7 +186,7 @@ fn integer_rad(rd: &mut PosReader, rad: u32) -> Result<Token, Err> {
false
};
let mut n: Number = 0;
let mut n = 0_i64;
loop {
match rd.next() {
@ -221,13 +218,12 @@ fn is_sym_init(c: char) -> bool {
| '/' | ':' | '<'
| '=' | '>' | '?'
| '~' | '_' | '^'
| '+' | '-'
)
}
fn is_sym_subs(c: char) -> bool {
is_sym_init(c)
|| c.is_numeric()
|| matches!(c, '0'..='9' | '.' | '+' | '-' | '@')
is_sym_init(c) || c.is_numeric() || matches!(c, '0'..='9' | '.' | '@')
}
fn symbol(rd: &mut PosReader, c: char) -> Result<Token, Err> {
@ -287,81 +283,83 @@ fn block_comment(rd: &mut PosReader) -> Result<(), Err> {
Ok(())
}
pub fn tokenize_from(name: &str, data: &str) -> Result<Vec<Token>, Err> {
use self::Type::*;
impl Token {
pub fn read_all(name: &str, data: &str) -> Result<Vec<Self>, Err> {
use self::Type::*;
let mut tokens = Vec::new();
let rd = &mut PosReader::new(data, text::ellipsize_small_str(name));
let mut tokens = Vec::new();
let rd = &mut PosReader::new(data, text::ellipsize_small_str(name));
while let Some(c) = rd.next() {
let tk = match c {
// line comments
';' => {
line_comment(rd)?;
continue;
}
while let Some(c) = rd.next() {
let tk = match c {
// line comments
';' => {
line_comment(rd)?;
continue;
}
// basic tokens
'(' => new_tok(rd, Br1O, Data::None),
')' => new_tok(rd, Br1C, Data::None),
'[' => new_tok(rd, Br3O, Data::None),
']' => new_tok(rd, Br3C, Data::None),
// basic tokens
'(' => new_tok(rd, Br1O, Data::None),
')' => new_tok(rd, Br1C, Data::None),
'[' => new_tok(rd, Br3O, Data::None),
']' => new_tok(rd, Br3C, Data::None),
'.' => new_tok(delim_end(rd)?, Peri, Data::None),
'.' => new_tok(delim_end(rd)?, Peri, Data::None),
// quote abbreviations
'\'' => new_tok(rd, Quot, Data::None),
'`' => new_tok(rd, QQuo, Data::None),
',' => unquote(rd, UnQS, UnQu),
// quote abbreviations
'\'' => new_tok(rd, Quot, Data::None),
'`' => new_tok(rd, QQuo, Data::None),
',' => unquote(rd, UnQS, UnQu),
// tokens preceded by #
'#' => match rd.next().ok_or(Err::Eof)? {
// block comments
'|' => {
block_comment(rd)?;
continue;
}
// tokens preceded by #
'#' => match rd.next().ok_or(Err::Eof)? {
// block comments
'|' => {
block_comment(rd)?;
continue;
}
// integers
'b' | 'B' => integer_rad(rd, 2)?,
'o' | 'O' => integer_rad(rd, 8)?,
'd' | 'D' => integer_rad(rd, 10)?,
'x' | 'X' => integer_rad(rd, 16)?,
// integers
'b' | 'B' => integer_rad(rd, 2)?,
'o' | 'O' => integer_rad(rd, 8)?,
'd' | 'D' => integer_rad(rd, 10)?,
'x' | 'X' => integer_rad(rd, 16)?,
// booleans
't' | 'T' => new_tok(delim_end(rd)?, Bool, Data::Bool(true)),
'f' | 'F' => new_tok(delim_end(rd)?, Bool, Data::Bool(false)),
// booleans
't' | 'T' => new_tok(delim_end(rd)?, Bool, Data::Bool(true)),
'f' | 'F' => new_tok(delim_end(rd)?, Bool, Data::Bool(false)),
// syntax abbreviations
'\'' => new_tok(rd, Synt, Data::None),
'`' => new_tok(rd, QSyn, Data::None),
',' => unquote(rd, UnSS, UnSy),
// syntax abbreviations
'\'' => new_tok(rd, Synt, Data::None),
'`' => new_tok(rd, QSyn, Data::None),
',' => unquote(rd, UnSS, UnSy),
// character literals
'\\' => char_lit(rd)?,
// character literals
'\\' => char_lit(rd)?,
c => return Err(Err::Char(rd.pos(), c)),
},
c => return Err(Err::Char(rd.pos(), c)),
},
// strings
'"' => strn_lit(rd)?,
// strings
'"' => strn_lit(rd)?,
// integers without prefixes
c if c.is_digit(10) => integer_rad(rd, 10)?,
// integers without prefixes
c if c.is_digit(10) => integer_rad(rd, 10)?,
// symbols
c if is_sym_init(c) => symbol(rd, c)?,
// symbols
c if is_sym_init(c) => symbol(rd, c)?,
// skip whitespace
c if c.is_whitespace() => continue,
// skip whitespace
c if c.is_whitespace() => continue,
c => return Err(Err::Char(rd.pos(), c)),
};
c => return Err(Err::Char(rd.pos(), c)),
};
tokens.push(tk);
}
tokens.push(tk);
}
Ok(tokens)
Ok(tokens)
}
}
// EOF

12
source/main_test/entry.rs

@ -347,13 +347,21 @@ pub fn run(
conf: &conf::Conf,
lg: &log::Log,
) -> Result<(), Box<dyn std::error::Error>> {
vire::compiler::compile_context()?;
/*
let start_time = std::time::Instant::now();
let mut vfs = vfs::Vfs::default();
vfs.add_arc(vfs::Arc::read_path("testres".as_ref())?);
//vire::compiler::Context::new()?;
dbg!(vire::parser::Datum::parse(dbg!(
&mut vire::parser::tki::TokenIter::from_data(
"main.vire.gz",
vfs.get("main.vire.gz")?.text()?
)?
))?);
/*
let concur_frames = conf.render.concurrent_frames.into();
let hal = hal::Context::new()?;

Loading…
Cancel
Save