Skip to content

Commit

Permalink
added eval
Browse files Browse the repository at this point in the history
  • Loading branch information
lexa-diky committed Jul 10, 2024
1 parent de43af1 commit d41e06e
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 47 deletions.
2 changes: 1 addition & 1 deletion 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
@@ -1,6 +1,6 @@
[package]
name = "hexo"
version = "0.8.0"
version = "0.9.0"
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/lexa-diky/hexo"
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ To call a function use glyph '#' fallowed by function name and arguments:
> #pad_left(AA, 4) // will emit '00 00 00 AA'
> #pad_right(AA, 4) // will emit 'AA 00 00 00'
> #pad('AA', left: 10x4, right: 10x8) // wil pad left by 4 bytes and right by 8 bytes
// Hexo compiler
> #eval('> 01 02 03') // will evaluate passed argument and return resulting compilation
```

### Example
Expand Down
2 changes: 1 addition & 1 deletion sample.hexo
Original file line number Diff line number Diff line change
@@ -1 +1 @@
> #pad('AA', left: 10x4, right: 10x8)
> #eval(#read_file('samples/java_object/input.hexo'))
30 changes: 29 additions & 1 deletion src/compiler/compiler_source.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::fmt::format;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
use crate::util::id::HexoId;
use crate::util::logger;

pub(crate) trait CompilerSource {
Expand Down Expand Up @@ -34,6 +36,33 @@ impl CompilerSource for FileCompilerSource {
}
}

pub(crate) struct LiteralCompilerSource {
content: String,
path: PathBuf,
}

impl CompilerSource for LiteralCompilerSource {
fn read(&self) -> Result<String, std::io::Error> {
Ok(self.content.clone())
}

fn path(&self) -> &Path {
self.path.as_path()
}
}

impl LiteralCompilerSource {
pub(crate) fn anonymous(content: String) -> LiteralCompilerSource {
LiteralCompilerSource {
content: content,
path: Path::new(
format!("hexo://anonymous/{}", HexoId::next()).as_str()
).to_path_buf(),
}
}
}


#[cfg(test)]
pub(crate) mod tests {
use std::fs::File;
Expand All @@ -57,7 +86,6 @@ pub(crate) mod tests {
}

impl EagerCompilerSource {

pub(crate) fn new<P: AsRef<Path>>(path: P) -> Result<Self, std::io::Error> {
let pat_ref = path.as_ref();
let mut source_file = File::open(pat_ref)?;
Expand Down
54 changes: 29 additions & 25 deletions src/compiler/native_fn/implementations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@ use crate::util::byte_buffer::ByteBuffer;
use std::collections::HashMap;
use std::fs::File;
use std::io::Read;

use crate::compiler::compiler_source::LiteralCompilerSource;
use crate::compiler::native_fn::error::Error;
use crate::compiler::native_fn::signature::{NativeFunction, NativeFunctionSignature};

pub(crate) fn create_len_native_function() -> NativeFunction {
NativeFunction {
signature: NativeFunctionSignature {
name: String::from("len"),
},
executor: |arguments: HashMap<String, ByteBuffer>| {
signature: NativeFunctionSignature::new("len"),
executor: |arguments: HashMap<String, ByteBuffer>, _| {
let mut result = ByteBuffer::default();
let arg0 = get_named_argument(&arguments, "utf8")
.unwrap_or_else(|| get_argument_at(&arguments, 0, "len").unwrap());
Expand All @@ -25,10 +23,8 @@ pub(crate) fn create_len_native_function() -> NativeFunction {

pub(crate) fn create_pad_left_native_function() -> NativeFunction {
NativeFunction {
signature: NativeFunctionSignature {
name: String::from("pad_left"),
},
executor: |arguments: HashMap<String, ByteBuffer>| {
signature: NativeFunctionSignature::new("pad_left"),
executor: |arguments: HashMap<String, ByteBuffer>, _| {
let mut arg0 = get_argument_at(&arguments, 0, "pad_left")?.clone();
let arg1 = get_argument_at(&arguments, 1, "pad_left")?;

Expand All @@ -41,10 +37,8 @@ pub(crate) fn create_pad_left_native_function() -> NativeFunction {

pub(crate) fn create_pad_right_native_function() -> NativeFunction {
NativeFunction {
signature: NativeFunctionSignature {
name: String::from("pad_right"),
},
executor: |arguments: HashMap<String, ByteBuffer>| {
signature: NativeFunctionSignature::new("pad_right"),
executor: |arguments: HashMap<String, ByteBuffer>, _| {
let mut arg0: ByteBuffer = get_argument_at(&arguments, 0, "pad_right")?.clone();
let arg1 = get_argument_at(&arguments, 1, "pad_right")?;

Expand All @@ -57,10 +51,8 @@ pub(crate) fn create_pad_right_native_function() -> NativeFunction {

pub(crate) fn create_cmd_native_function() -> NativeFunction {
NativeFunction {
signature: NativeFunctionSignature {
name: String::from("cmd"),
},
executor: |arguments: HashMap<String, ByteBuffer>| {
signature: NativeFunctionSignature::new("cmd"),
executor: |arguments: HashMap<String, ByteBuffer>, _| {
let command = get_argument_at(&arguments, 0, "cmd")?
.to_string()
.map_err(|e| Error::Unknown(e.to_string()))?;
Expand All @@ -78,10 +70,8 @@ pub(crate) fn create_cmd_native_function() -> NativeFunction {

pub(crate) fn create_read_file_native_function() -> NativeFunction {
return NativeFunction {
signature: NativeFunctionSignature {
name: String::from("read_file"),
},
executor: |arguments: HashMap<String, ByteBuffer>| {
signature: NativeFunctionSignature::new("read_file"),
executor: |arguments: HashMap<String, ByteBuffer>, _| {
let arg0 = get_argument_at(&arguments, 0, "read_file")?;

let file_path = arg0
Expand All @@ -104,10 +94,8 @@ pub(crate) fn create_read_file_native_function() -> NativeFunction {

pub(crate) fn create_pad_native_function() -> NativeFunction {
return NativeFunction {
signature: NativeFunctionSignature {
name: String::from("pad"),
},
executor: |arguments: HashMap<String, ByteBuffer>| {
signature: NativeFunctionSignature::new("pad"),
executor: |arguments: HashMap<String, ByteBuffer>, _| {
let mut buffer = get_argument_at(&arguments, 0, "pad")?.clone();

let left_padding = get_named_argument(&arguments, "left").map(|b| b.as_usize_unsafe());
Expand All @@ -126,6 +114,22 @@ pub(crate) fn create_pad_native_function() -> NativeFunction {
};
}

pub(crate) fn create_eval_native_function() -> NativeFunction {
return NativeFunction {
signature: NativeFunctionSignature::new("eval"),
executor: |arguments: HashMap<String, ByteBuffer>, compiler| {
let buffer = get_argument_at(&arguments, 0, "eval")?.clone();
let source = LiteralCompilerSource::anonymous(
buffer.to_string()
.map_err(|e| Error::Unknown(e.to_string()))?,
);
let result = compiler.compile(&source)
.map_err(|e| Error::Unknown(e.to_string()))?;
Ok(ByteBuffer::from(result.content))
},
};
}

fn get_argument_at<'a>(
arguments: &'a HashMap<String, ByteBuffer>,
pos: usize,
Expand Down
6 changes: 2 additions & 4 deletions src/compiler/native_fn/index.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
use crate::compiler::native_fn::signature::NativeFunction;
use crate::compiler::native_fn::{
create_cmd_native_function, create_len_native_function, create_pad_left_native_function,
create_pad_native_function, create_pad_right_native_function, create_read_file_native_function,
};
use crate::compiler::native_fn::{create_cmd_native_function, create_eval_native_function, create_len_native_function, create_pad_left_native_function, create_pad_native_function, create_pad_right_native_function, create_read_file_native_function};

#[derive(Clone, Debug)]
pub(crate) struct NativeFunctionIndex {
Expand All @@ -28,6 +25,7 @@ impl NativeFunctionIndex {
create_cmd_native_function(),
create_read_file_native_function(),
create_pad_native_function(),
create_eval_native_function()
]
}
}
11 changes: 10 additions & 1 deletion src/compiler/native_fn/signature.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
use crate::compiler::native_fn::error::Error;
use crate::util::byte_buffer::ByteBuffer;
use std::collections::HashMap;
use crate::compiler::HexoCompiler;

#[derive(Clone, Debug)]
pub(crate) struct NativeFunctionSignature {
pub(crate) name: String,
}

type NativeFunctionExecutor = fn(HashMap<String, ByteBuffer>) -> Result<ByteBuffer, Error>;
impl NativeFunctionSignature {
pub(crate) fn new(name: &str) -> NativeFunctionSignature {
NativeFunctionSignature {
name: String::from(name),
}
}
}

type NativeFunctionExecutor = fn(HashMap<String, ByteBuffer>, &HexoCompiler) -> Result<ByteBuffer, Error>;

#[derive(Clone, Debug)]
pub(crate) struct NativeFunction {
Expand Down
33 changes: 20 additions & 13 deletions src/compiler/rst/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ impl RstCompiler<'_> {

pub(crate) fn compile(&self, cst: &CstFile) -> Result<HexoFile, Error> {
let context_id = HexoId::next();
let mut context = Self::build_context(context_id, cst.path(), cst.main())?;
let mut context = self.build_context(context_id, cst.path(), cst.main())?;

let bb = Self::build_bytes(context_id, &mut context, cst.main().emits())?;
let bb = self.build_bytes(context_id, &mut context, cst.main().emits())?;

Ok(HexoFile {
path: cst.path().to_path_buf(),
Expand All @@ -35,20 +35,22 @@ impl RstCompiler<'_> {
}

fn build_bytes(
&self,
context_id: HexoId,
context: &mut CompilationContext,
emits: &Vec<CstEmitStatement>,
) -> Result<ByteBuffer, Error> {
let mut byte_buffer = ByteBuffer::default();

for emit in emits {
Self::build_bytes_into(context_id, context, emit.atoms(), &mut byte_buffer)?
self.build_bytes_into(context_id, context, emit.atoms(), &mut byte_buffer)?
}

Ok(byte_buffer)
}

fn build_bytes_into(
&self,
context_id: HexoId,
context: &mut CompilationContext,
atoms: &CstAtomVec,
Expand All @@ -63,7 +65,7 @@ impl RstCompiler<'_> {
Self::build_constant_into(context_id, context, name, buffer)?
}
CstAtom::Function { name, params } => {
Self::build_function_into(context_id, context, name.clone(), params, buffer)?
self.build_function_into(context_id, context, name.clone(), params, buffer)?
}
}
}
Expand All @@ -72,6 +74,7 @@ impl RstCompiler<'_> {
}

fn build_function_into(
&self,
context_id: HexoId,
context: &mut CompilationContext,
function_name: String,
Expand All @@ -85,13 +88,13 @@ impl RstCompiler<'_> {

for param in params {
let mut param_buffer = ByteBuffer::default();
Self::build_bytes_into(context_id, context, param.value(), &mut param_buffer)
self.build_bytes_into(context_id, context, param.value(), &mut param_buffer)
.unwrap();

params_buffer.insert(param.name().to_string(), param_buffer);
}

executor(params_buffer.clone())
executor(params_buffer.clone(), self.parent)
.map(|bb| buffer.push_byte_buffer(&bb))
.map_err(Error::NativeFunctionExecution)?;

Expand All @@ -107,7 +110,7 @@ impl RstCompiler<'_> {

for param in params {
let mut param_buffer = ByteBuffer::default();
Self::build_bytes_into(context_id, context, param.value(), &mut param_buffer).unwrap();
self.build_bytes_into(context_id, context, param.value(), &mut param_buffer).unwrap();

context.bind_local_constant(
function_binding.identifier,
Expand All @@ -119,7 +122,7 @@ impl RstCompiler<'_> {
}

for emit in &function_binding.emits {
Self::build_bytes_into(function_binding.identifier, context, emit.atoms(), buffer)
self.build_bytes_into(function_binding.identifier, context, emit.atoms(), buffer)
.unwrap();
}

Expand All @@ -142,35 +145,38 @@ impl RstCompiler<'_> {
}

fn build_context(
&self,
context_id: HexoId,
file_path: &Path,
cst: &CstFunctionStatement,
) -> Result<CompilationContext, Error> {
let mut root_context = CompilationContext::new(file_path);

Self::build_context_into(context_id, &cst, &mut root_context)?;
self.build_context_into(context_id, &cst, &mut root_context)?;

Ok(root_context)
}

fn build_context_into(
&self,
context_id: HexoId,
cst: &&CstFunctionStatement,
root_context: &mut CompilationContext,
) -> Result<(), Error> {
Self::build_context_constants_into(context_id, cst, root_context)?;
Self::build_context_functions_into(context_id, cst, root_context)?;
self.build_context_constants_into(context_id, cst, root_context)?;
self.build_context_functions_into(context_id, cst, root_context)?;
Ok(())
}

fn build_context_constants_into(
&self,
context_id: HexoId,
cst: &&CstFunctionStatement,
context: &mut CompilationContext,
) -> Result<(), Error> {
for constant in cst.constants() {
let mut buff = ByteBuffer::default();
Self::build_bytes_into(context_id, context, constant.atoms(), &mut buff)?;
self.build_bytes_into(context_id, context, constant.atoms(), &mut buff)?;
context.bind_local_constant(
context_id,
ConstantBinding {
Expand All @@ -184,6 +190,7 @@ impl RstCompiler<'_> {
}

fn build_context_functions_into(
&self,
context_id: HexoId,
cst: &&CstFunctionStatement,
root_context: &mut CompilationContext,
Expand All @@ -199,7 +206,7 @@ impl RstCompiler<'_> {
},
);

Self::build_context_into(inner_function_context_id, &function, root_context)?;
self.build_context_into(inner_function_context_id, &function, root_context)?;

root_context.bind_parents(inner_function_context_id, vec![context_id]);
}
Expand Down

0 comments on commit d41e06e

Please sign in to comment.