Lines
100 %
Functions
Branches
use super::entry::{Symbol, SymbolKind};
use super::table::SymbolTable;
use crate::ast::Expr;
#[test]
fn test_symbol_creation() {
let sym = Symbol::new("foo", SymbolKind::Variable);
assert_eq!(sym.name(), "foo");
assert_eq!(sym.kind(), SymbolKind::Variable);
assert!(sym.value().is_none());
}
fn test_symbol_with_value() {
let sym = Symbol::new("x", SymbolKind::Variable).with_value(Expr::Bool(true));
assert!(sym.value().is_some());
assert_eq!(sym.value(), Some(&Expr::Bool(true)));
fn test_symbol_properties() {
let mut sym = Symbol::new("test", SymbolKind::Function);
sym.set_property("doc", Expr::String("A test function".into()));
sym.set_property("pure", Expr::Bool(true));
assert_eq!(
sym.get_property("doc"),
Some(&Expr::String("A test function".into()))
);
assert_eq!(sym.get_property("pure"), Some(&Expr::Bool(true)));
assert!(sym.get_property("nonexistent").is_none());
fn test_symbol_table_builtins() {
let table = SymbolTable::with_builtins();
assert!(table.contains("+"));
assert_eq!(table.lookup("+").unwrap().kind(), SymbolKind::Operator);
assert!(table.contains("IF"));
assert_eq!(table.lookup("IF").unwrap().kind(), SymbolKind::SpecialForm);
assert!(table.contains("CAR"));
assert_eq!(table.lookup("CAR").unwrap().kind(), SymbolKind::Native);
assert!(table.contains("EVAL"));
table.lookup("EVAL").unwrap().kind(),
SymbolKind::SpecialForm
assert!(table.contains("DEBUG"));
assert_eq!(table.lookup("DEBUG").unwrap().kind(), SymbolKind::Native);
fn test_symbol_table_define_lookup() {
let mut table = SymbolTable::new();
table.define(Symbol::new("my-func", SymbolKind::Function));
assert!(table.contains("my-func"));
assert!(!table.contains("undefined"));
let sym = table.lookup("my-func").unwrap();
assert_eq!(sym.kind(), SymbolKind::Function);
// ADR-0029 strict resolution: a namespaced symbol keys by its canonical
// `NS:NAME` string and does NOT alias the bare `NAME`. There is no ambient
// current namespace and no cross-namespace fallback.
fn qualified_symbol_keys_separately_from_bare() {
table.define(Symbol::new("FOO:BAR", SymbolKind::Function));
assert!(table.contains("FOO:BAR"));
// Strict: the qualified key does not create a bare alias.
assert!(!table.contains("BAR"));
assert!(table.lookup("FOO:BAR").is_some());
assert!(table.lookup("BAR").is_none());
fn lookup_qualified_builds_canonical_key() {
table.define(Symbol::new("FINANCE:ADD-MONEY", SymbolKind::Function));
assert!(
table
.lookup_qualified(Some("FINANCE"), "ADD-MONEY")
.is_some()
// An unqualified lookup of the same base name does not reach the namespaced entry.
assert!(table.lookup_qualified(None, "ADD-MONEY").is_none());
fn builtins_remain_global_unqualified() {
// Global builtins keep bare keys; a namespaced lookup of the same base misses.
assert!(!table.contains("MATH:+"));
assert!(table.lookup_qualified(Some("MATH"), "+").is_none());
fn universal_prelude_loaded_but_not_host_layer() {
// ADR-0029 two-layer prelude: the universal math:* / list:* helpers are
// present in every table; the host-fn-dependent split:* helpers are NOT
// (they load only on the rpc Session path, after host fns are registered).
assert!(table.contains("MATH:SQUARE"));
assert!(table.contains("LIST:SECOND"));
assert!(!table.contains("SPLIT:LIST-FOR-TRANSACTION"));
// The pure-wasm table loads the same universal layer.
let wasm_table = SymbolTable::with_builtins_for_wasm();
assert!(wasm_table.contains("MATH:SQUARE"));
assert!(!wasm_table.contains("SPLIT:LIST-FOR-TRANSACTION"));