Refactor series implementation into its own module
This commit reorganizes the series-related code by moving the `RingBuffer`, `ScalarSeries`, `ValueSeries`, `RecordSeries`, `SeriesView`, and `SharedSeries` structs into a new `src/ast/rtl/series/data.rs` file. The `src/ast/rtl/series/mod.rs` file now contains the module declaration, re-exports, and the `register` function for registering series-related native functions with the environment. This improves code organization and maintainability.
This commit is contained in:
@@ -19,7 +19,7 @@ use crate::ast::compiler::lambda_collector::LambdaCollector;
|
|||||||
use crate::ast::compiler::lowering::Lowering;
|
use crate::ast::compiler::lowering::Lowering;
|
||||||
use crate::ast::compiler::macros::{MacroEvaluator, MacroExpander, MacroRegistry};
|
use crate::ast::compiler::macros::{MacroEvaluator, MacroExpander, MacroRegistry};
|
||||||
use crate::ast::compiler::optimizer::Optimizer;
|
use crate::ast::compiler::optimizer::Optimizer;
|
||||||
use crate::ast::compiler::specializer::{FunctionRegistry, MonoCache, Specializer};
|
use crate::ast::compiler::specializer::{FunctionRegistry, MonoCache, RtlLookupFunc, Specializer};
|
||||||
use crate::ast::rtl::{self, intrinsics};
|
use crate::ast::rtl::{self, intrinsics};
|
||||||
use crate::ast::types::{
|
use crate::ast::types::{
|
||||||
NativeFunction, NodeIdentity, Purity, SourceLocation, StaticType, Value,
|
NativeFunction, NodeIdentity, Purity, SourceLocation, StaticType, Value,
|
||||||
@@ -28,8 +28,12 @@ use crate::ast::types::{
|
|||||||
use crate::ast::diagnostics::{DiagnosticLevel, Diagnostics};
|
use crate::ast::diagnostics::{DiagnosticLevel, Diagnostics};
|
||||||
pub type PipelineGenerator = Box<dyn FnMut() -> bool>;
|
pub type PipelineGenerator = Box<dyn FnMut() -> bool>;
|
||||||
|
|
||||||
const SYSTEM_LIB_SOURCE: &str = include_str!("system.myc");
|
const SYSTEM_LIB_SOURCE: &str = include_str!("rtl/prelude.myc");
|
||||||
const SYSTEM_LIB_PATH: &str = "<embedded>/system.myc";
|
const SYSTEM_LIB_PATH: &str = "<embedded>/prelude.myc";
|
||||||
|
|
||||||
|
fn make_rtl_lookup() -> RtlLookupFunc {
|
||||||
|
Rc::new(|name: &str, args: &[StaticType]| intrinsics::lookup(name, args))
|
||||||
|
}
|
||||||
|
|
||||||
pub struct CompilationResult {
|
pub struct CompilationResult {
|
||||||
pub ast: Option<TypedNode>,
|
pub ast: Option<TypedNode>,
|
||||||
@@ -707,7 +711,7 @@ impl Environment {
|
|||||||
analyzed_registry: self.typed_function_registry.clone(),
|
analyzed_registry: self.typed_function_registry.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let rtl_lookup = Rc::new(|name: &str, args: &[StaticType]| intrinsics::lookup(name, args));
|
let rtl_lookup = make_rtl_lookup();
|
||||||
let typed_reg = self.typed_function_registry.clone();
|
let typed_reg = self.typed_function_registry.clone();
|
||||||
let mono_cache = self.monomorph_cache.clone();
|
let mono_cache = self.monomorph_cache.clone();
|
||||||
let root_values = self.root_values.clone();
|
let root_values = self.root_values.clone();
|
||||||
@@ -755,8 +759,7 @@ impl Environment {
|
|||||||
let sub_registry = Rc::new(EnvFunctionRegistry {
|
let sub_registry = Rc::new(EnvFunctionRegistry {
|
||||||
analyzed_registry: typed_reg.clone(),
|
analyzed_registry: typed_reg.clone(),
|
||||||
});
|
});
|
||||||
let sub_rtl_lookup =
|
let sub_rtl_lookup = make_rtl_lookup();
|
||||||
Rc::new(|name: &str, args: &[StaticType]| intrinsics::lookup(name, args));
|
|
||||||
|
|
||||||
let sub_specializer = Specializer::new(
|
let sub_specializer = Specializer::new(
|
||||||
Some(sub_registry),
|
Some(sub_registry),
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,100 @@
|
|||||||
|
pub mod data;
|
||||||
|
pub use data::*;
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use crate::ast::environment::Environment;
|
||||||
|
use crate::ast::types::{Purity, RecordLayout, Signature, StaticType, Value};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 5. Script Integration (RTL Registration)
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
pub fn register(env: &Environment) {
|
||||||
|
// (series lookback_limit template_or_type_keyword) -> Series
|
||||||
|
env.register_native_fn(
|
||||||
|
"series",
|
||||||
|
StaticType::Function(Box::new(Signature {
|
||||||
|
params: StaticType::Tuple(vec![StaticType::Int, StaticType::Any]),
|
||||||
|
ret: StaticType::Any,
|
||||||
|
})),
|
||||||
|
Purity::Impure,
|
||||||
|
|args: &[Value]| {
|
||||||
|
let lookback_limit = args[0].as_int().unwrap_or(0) as usize;
|
||||||
|
let arg = &args[1];
|
||||||
|
match arg {
|
||||||
|
Value::Keyword(k) => {
|
||||||
|
match k.name().to_lowercase().as_str() {
|
||||||
|
"float" => Value::Object(Rc::new(ScalarSeries::<f64>::new("FloatSeries", lookback_limit))),
|
||||||
|
"int" | "datetime" => Value::Object(Rc::new(ScalarSeries::<i64>::new("IntSeries", lookback_limit))),
|
||||||
|
"bool" => Value::Object(Rc::new(ScalarSeries::<bool>::new("BoolSeries", lookback_limit))),
|
||||||
|
"text" => Value::Object(Rc::new(ValueSeries::new(lookback_limit))),
|
||||||
|
_ => panic!("Unknown or unsupported series type keyword: :{}", k.name()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::Record(schema_layout, schema_values) => {
|
||||||
|
// Interpret the record as a schema: { :field :type_keyword }
|
||||||
|
let mut fields = Vec::with_capacity(schema_layout.fields.len());
|
||||||
|
for (i, (name, _)) in schema_layout.fields.iter().enumerate() {
|
||||||
|
let type_keyword = match &schema_values[i] {
|
||||||
|
Value::Keyword(tk) => tk.name().to_lowercase(),
|
||||||
|
_ => panic!("Field :{} in series schema must be a type keyword (e.g., :float, :int)", name.name()),
|
||||||
|
};
|
||||||
|
let ty = match type_keyword.as_str() {
|
||||||
|
"float" => StaticType::Float,
|
||||||
|
"int" => StaticType::Int,
|
||||||
|
"bool" => StaticType::Bool,
|
||||||
|
"datetime" => StaticType::DateTime,
|
||||||
|
"text" => StaticType::Text,
|
||||||
|
_ => panic!("Unsupported type keyword :{} for series field :{}", type_keyword, name.name()),
|
||||||
|
};
|
||||||
|
fields.push((*name, ty));
|
||||||
|
}
|
||||||
|
let final_layout = RecordLayout::get_or_create(fields);
|
||||||
|
Value::Object(Rc::new(RecordSeries::new(final_layout, lookback_limit)))
|
||||||
|
}
|
||||||
|
_ => panic!("series expects a lookback_limit and a type keyword (:float, :int...) or a schema record (e.g., {{:price :float}})"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// (push series value) -> Void
|
||||||
|
env.register_native_fn(
|
||||||
|
"push",
|
||||||
|
StaticType::Function(Box::new(Signature {
|
||||||
|
params: StaticType::Tuple(vec![StaticType::Any, StaticType::Any]),
|
||||||
|
ret: StaticType::Void,
|
||||||
|
})),
|
||||||
|
Purity::Impure,
|
||||||
|
|args: &[Value]| {
|
||||||
|
let (series_val, val) = (&args[0], &args[1]);
|
||||||
|
|
||||||
|
if let Value::Object(obj) = series_val {
|
||||||
|
if let Some(p) = obj.as_pushable_series() {
|
||||||
|
p.push_value(val.clone());
|
||||||
|
return Value::Void;
|
||||||
|
}
|
||||||
|
panic!("push expects a pushable series, got: {}", obj.type_name());
|
||||||
|
}
|
||||||
|
panic!("push expects a series object as the first argument")
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// (len series) -> Int
|
||||||
|
env.register_native_fn(
|
||||||
|
"len",
|
||||||
|
StaticType::Function(Box::new(Signature {
|
||||||
|
params: StaticType::Tuple(vec![StaticType::Any]),
|
||||||
|
ret: StaticType::Int,
|
||||||
|
})),
|
||||||
|
Purity::Pure,
|
||||||
|
|args: &[Value]| {
|
||||||
|
if let Value::Object(obj) = &args[0]
|
||||||
|
&& let Some(s) = obj.as_series()
|
||||||
|
{
|
||||||
|
return Value::Int(s.len() as i64);
|
||||||
|
}
|
||||||
|
Value::Int(0)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user