#![allow(unused_variables)] use std::fmt::Debug; pub use eval_res::EvalRes; use sexp::{Sexp, SourcePosition}; use crate::asm::data::literal::Value; use crate::asm::error::CrsnError; use crate::asm::instr::Flatten; use crate::asm::instr::op::OpKind; use crate::asm::parse::arg_parser::TokenParser; use crate::runtime::fault::Fault; use crate::runtime::run_thread::state::RunState; use crate::runtime::run_thread::ThreadInfo; use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::Arc; use crate::asm::data::Wr; use crate::builtin::defs::BuiltinOp; mod eval_res; /// Result type returned from the op parser. This is the Ok variant of a Result. pub enum ParseRes<'a, T> { /// Parsing successful. Parsed(T), /// Parsing successful, but did not yield any result ParsedNone, /// Instruction not recognized, but there was no error. Unknown(TokenParser<'a>), } impl ParseRes<'static, OpKind> { pub fn builtin(op: BuiltinOp) -> ParseRes<'static, OpKind> { Self::Parsed(OpKind::BuiltIn(op)) } } impl<'a> ParseRes<'a, OpKind> { /// Helper to construct an extension op pub fn ext(op: impl OpTrait) -> Self { Self::Parsed(OpKind::Ext(Box::new(op))) } } pub trait OpTrait: Debug + Send + Sync + 'static { fn execute(&self, ti: &ThreadInfo, state: &mut RunState) -> Result; /// Turn into an S-expression that produces this instruction when parsed fn to_sexp(&self) -> Sexp; } /// CRSN initializer object. /// Only one should be created for the lifespan of the parser and runtime. #[derive(Default,Debug)] pub struct CrsnUniq { object_handle_counter : AtomicU64 } pub const UNIQ_BASE: u64 = 0x6372_736e_0000_0000; impl CrsnUniq { pub fn new() -> Arc { Arc::new(Self { object_handle_counter: AtomicU64::new(UNIQ_BASE), }) } pub fn unique_handle(&self) -> u64 { self.object_handle_counter.fetch_add(1, Ordering::Relaxed) } } pub trait CrsnExtension: Debug + Send + Sync + 'static { fn init(&mut self, uniq: &CrsnUniq) { // } /// Get name of the module fn name(&self) -> &'static str; /// Parse an op. /// If the keyword matches and the function decides to parse the instruction, it must consume /// the argument list and either return Ok or Err. /// /// If the instruction keyword is not recognized, return Unknown with the unchanged argument list. /// /// pcx is available on the arg_tokens parser fn parse_op<'a>(&self, pos: &SourcePosition, keyword: &str, arg_tokens: TokenParser<'a>) -> Result, CrsnError>; /// Parse a generic S-expression (non-op) that started with the given keyword /// /// pcx is available on the arg_tokens parser fn parse_syntax<'a>(&self, pos: &SourcePosition, keyword: &str, tokens: TokenParser<'a>) -> Result>, CrsnError> { Ok(ParseRes::Unknown(tokens)) } /// Get value of an extension-provided constant. /// This constant may be an object handle, or a constant value used as argument in some other instruction. fn get_constant_value<'a>(&self, name: &str) -> Option { None } /// Drop an object referenced by a handle fn drop_obj(&self, ti: &ThreadInfo, state: &mut RunState, handle: Value) -> Result, Fault> { // Default impl - we do not support dropping this object Ok(None) } /// Run-time method called to read an object ("ld" and its variants, using the object handle syntax) fn read_obj(&self, state: &mut RunState, handle: Value) -> Result, Fault> { // Default impl - we do not support reading this object Ok(None) } /// Run-time method called to read all values from an object ("lds" using the object handle syntax) fn read_obj_all(&self, state: &mut RunState, whandle: Wr, rhandle: Value) -> Result, Fault> { // Default impl - we do not support reading this object Ok(None) } /// Run-time method called to write an object (using the object handle syntax) fn write_obj(&self, state: &mut RunState, handle: Value, value: Value) -> Result, Fault> { // Default impl - we do not support writing this object Ok(None) } }