mirror of
https://github.com/exoticorn/curlywas.git
synced 2026-01-20 11:46:43 +01:00
add ability to include file as data
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
use std::fmt;
|
use std::{fmt, path::PathBuf};
|
||||||
|
|
||||||
use crate::Span;
|
use crate::Span;
|
||||||
|
|
||||||
@@ -73,6 +73,10 @@ pub enum DataValues {
|
|||||||
values: Vec<Expression>,
|
values: Vec<Expression>,
|
||||||
},
|
},
|
||||||
String(String),
|
String(String),
|
||||||
|
File {
|
||||||
|
path: PathBuf,
|
||||||
|
data: Vec<u8>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ pub fn fold_script(script: &mut ast::Script) {
|
|||||||
fold_expr(value);
|
fold_expr(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::DataValues::String(_) => (),
|
ast::DataValues::String(_) | ast::DataValues::File { .. } => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,6 +173,9 @@ pub fn emit(script: &ast::Script) -> Vec<u8> {
|
|||||||
segment_data.push(c as u8);
|
segment_data.push(c as u8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast::DataValues::File { data, .. } => {
|
||||||
|
segment_data.extend_from_slice(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data_section.active(
|
data_section.active(
|
||||||
|
|||||||
31
src/includes.rs
Normal file
31
src/includes.rs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
use std::fs::File;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use crate::ast;
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
|
||||||
|
pub fn resolve_includes(script: &mut ast::Script, path: &Path) -> Result<()> {
|
||||||
|
let script_dir = path.parent().expect("Script path has no parent");
|
||||||
|
for data in &mut script.data {
|
||||||
|
for values in &mut data.data {
|
||||||
|
match values {
|
||||||
|
ast::DataValues::File {
|
||||||
|
ref path,
|
||||||
|
ref mut data,
|
||||||
|
} => {
|
||||||
|
let mut full_path = script_dir.to_path_buf();
|
||||||
|
full_path.push(path);
|
||||||
|
File::open(&full_path)
|
||||||
|
.map_err(|e| {
|
||||||
|
anyhow!("Failed to load data from {}: {}", full_path.display(), e)
|
||||||
|
})?
|
||||||
|
.read_to_end(data)?;
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -8,22 +8,26 @@ mod emit;
|
|||||||
mod intrinsics;
|
mod intrinsics;
|
||||||
mod parser;
|
mod parser;
|
||||||
mod typecheck;
|
mod typecheck;
|
||||||
|
mod includes;
|
||||||
|
|
||||||
type Span = std::ops::Range<usize>;
|
type Span = std::ops::Range<usize>;
|
||||||
|
|
||||||
pub fn compile_file<P: AsRef<Path>>(path: P) -> Result<Vec<u8>> {
|
pub fn compile_file<P: AsRef<Path>>(path: P) -> Result<Vec<u8>> {
|
||||||
|
let path = path.as_ref();
|
||||||
let mut input = String::new();
|
let mut input = String::new();
|
||||||
File::open(path)?.read_to_string(&mut input)?;
|
File::open(path)?.read_to_string(&mut input)?;
|
||||||
|
|
||||||
compile_str(&input)
|
compile_str(&input, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_str(input: &str) -> Result<Vec<u8>> {
|
pub fn compile_str(input: &str, path: &Path) -> Result<Vec<u8>> {
|
||||||
let mut script = match parser::parse(&input) {
|
let mut script = match parser::parse(&input) {
|
||||||
Ok(script) => script,
|
Ok(script) => script,
|
||||||
Err(_) => bail!("Parse failed"),
|
Err(_) => bail!("Parse failed"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
includes::resolve_includes(&mut script, path)?;
|
||||||
|
|
||||||
constfold::fold_script(&mut script);
|
constfold::fold_script(&mut script);
|
||||||
if let Err(_) = typecheck::tc_script(&mut script, &input) {
|
if let Err(_) = typecheck::tc_script(&mut script, &input) {
|
||||||
bail!("Type check failed");
|
bail!("Type check failed");
|
||||||
|
|||||||
@@ -863,13 +863,25 @@ fn script_parser() -> impl Parser<Token, ast::Script, Error = Simple<Token>> + C
|
|||||||
)
|
)
|
||||||
.map(|(type_, values)| ast::DataValues::Array { type_, values });
|
.map(|(type_, values)| ast::DataValues::Array { type_, values });
|
||||||
|
|
||||||
let data_string = string.map(|s| ast::DataValues::String(s));
|
let data_string = string.clone().map(|s| ast::DataValues::String(s));
|
||||||
|
|
||||||
|
let data_file = just(Token::Ident("file".to_string()))
|
||||||
|
.ignore_then(
|
||||||
|
string
|
||||||
|
.clone()
|
||||||
|
.delimited_by(Token::Ctrl('('), Token::Ctrl(')')),
|
||||||
|
)
|
||||||
|
.map(|s| ast::DataValues::File {
|
||||||
|
path: s.into(),
|
||||||
|
data: vec![],
|
||||||
|
});
|
||||||
|
|
||||||
let data = just(Token::Ident("data".to_string()))
|
let data = just(Token::Ident("data".to_string()))
|
||||||
.ignore_then(expression.clone())
|
.ignore_then(expression.clone())
|
||||||
.then(
|
.then(
|
||||||
data_i8
|
data_i8
|
||||||
.or(data_string)
|
.or(data_string)
|
||||||
|
.or(data_file)
|
||||||
.repeated()
|
.repeated()
|
||||||
.delimited_by(Token::Ctrl('{'), Token::Ctrl('}')),
|
.delimited_by(Token::Ctrl('{'), Token::Ctrl('}')),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ pub fn tc_script(script: &mut ast::Script, source: &str) -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::DataValues::String(_) => (),
|
ast::DataValues::String(_) | ast::DataValues::File { .. } => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user