pr 64
This commit is contained in:
parent
3af2aa1328
commit
6cf1e71b99
@ -237,14 +237,19 @@ impl Linker {
|
|||||||
if let Some(local_func_idx) = meta.func_idx {
|
if let Some(local_func_idx) = meta.func_idx {
|
||||||
let global_func_idx = module_function_offsets.last().unwrap() + local_func_idx;
|
let global_func_idx = module_function_offsets.last().unwrap() + local_func_idx;
|
||||||
final_exports.insert(format!("{}:{}", key.module_path, key.symbol_name), global_func_idx);
|
final_exports.insert(format!("{}:{}", key.module_path, key.symbol_name), global_func_idx);
|
||||||
|
// Also provide short name for root module exports to facilitate entrypoint resolution
|
||||||
|
if !final_exports.contains_key(&key.symbol_name) {
|
||||||
|
final_exports.insert(key.symbol_name.clone(), global_func_idx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// v0: Fallback export for entrypoint `src/main/modules:frame` (root module)
|
// v0: Fallback export for entrypoint `frame` (root module)
|
||||||
if !final_exports.iter().any(|(name, _)| name.ends_with(":frame")) {
|
if !final_exports.iter().any(|(name, _)| name.ends_with(":frame") || name == "frame") {
|
||||||
if let Some(&root_offset) = module_function_offsets.last() {
|
if let Some(&root_offset) = module_function_offsets.last() {
|
||||||
if let Some((idx, _)) = combined_function_names.iter().find(|(i, name)| *i >= root_offset && name == "frame") {
|
if let Some((idx, _)) = combined_function_names.iter().find(|(i, name)| *i >= root_offset && name == "frame") {
|
||||||
|
final_exports.insert("frame".to_string(), *idx);
|
||||||
final_exports.insert("src/main/modules:frame".to_string(), *idx);
|
final_exports.insert("src/main/modules:frame".to_string(), *idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -274,9 +279,9 @@ mod tests {
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::building::output::{ExportKey, ExportMetadata, ImportKey, ImportMetadata};
|
use crate::building::output::{ExportKey, ExportMetadata, ImportKey, ImportMetadata};
|
||||||
|
use crate::semantics::export_surface::ExportSurfaceKind;
|
||||||
use crate::building::plan::BuildTarget;
|
use crate::building::plan::BuildTarget;
|
||||||
use crate::deps::resolver::ProjectId;
|
use crate::deps::resolver::ProjectId;
|
||||||
use crate::frontends::pbs::symbols::SymbolKind;
|
|
||||||
use prometeu_bytecode::opcode::OpCode;
|
use prometeu_bytecode::opcode::OpCode;
|
||||||
use prometeu_bytecode::FunctionMeta;
|
use prometeu_bytecode::FunctionMeta;
|
||||||
|
|
||||||
@ -294,7 +299,7 @@ mod tests {
|
|||||||
lib_exports.insert(ExportKey {
|
lib_exports.insert(ExportKey {
|
||||||
module_path: "math".into(),
|
module_path: "math".into(),
|
||||||
symbol_name: "add".into(),
|
symbol_name: "add".into(),
|
||||||
kind: SymbolKind::Function,
|
kind: ExportSurfaceKind::Service,
|
||||||
}, ExportMetadata { func_idx: Some(0), is_host: false, ty: None });
|
}, ExportMetadata { func_idx: Some(0), is_host: false, ty: None });
|
||||||
|
|
||||||
let lib_module = CompiledModule {
|
let lib_module = CompiledModule {
|
||||||
|
|||||||
@ -12,6 +12,7 @@ use crate::frontends::pbs::resolver::{ModuleProvider, Resolver};
|
|||||||
use crate::frontends::pbs::symbols::{ModuleSymbols, Namespace, Symbol, SymbolKind, Visibility};
|
use crate::frontends::pbs::symbols::{ModuleSymbols, Namespace, Symbol, SymbolKind, Visibility};
|
||||||
use crate::frontends::pbs::typecheck::TypeChecker;
|
use crate::frontends::pbs::typecheck::TypeChecker;
|
||||||
use crate::frontends::pbs::types::PbsType;
|
use crate::frontends::pbs::types::PbsType;
|
||||||
|
use crate::semantics::export_surface::ExportSurfaceKind;
|
||||||
use crate::lowering::core_to_vm;
|
use crate::lowering::core_to_vm;
|
||||||
use prometeu_bytecode::{ConstantPoolEntry, DebugInfo, FunctionMeta};
|
use prometeu_bytecode::{ConstantPoolEntry, DebugInfo, FunctionMeta};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -22,7 +23,7 @@ use std::path::Path;
|
|||||||
pub struct ExportKey {
|
pub struct ExportKey {
|
||||||
pub module_path: String,
|
pub module_path: String,
|
||||||
pub symbol_name: String,
|
pub symbol_name: String,
|
||||||
pub kind: SymbolKind,
|
pub kind: ExportSurfaceKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -165,12 +166,17 @@ pub fn compile_project(
|
|||||||
|
|
||||||
let sym = Symbol {
|
let sym = Symbol {
|
||||||
name: key.symbol_name.clone(),
|
name: key.symbol_name.clone(),
|
||||||
kind: key.kind.clone(),
|
kind: match key.kind {
|
||||||
namespace: match key.kind {
|
ExportSurfaceKind::Service => SymbolKind::Service,
|
||||||
SymbolKind::Function | SymbolKind::Service => Namespace::Value,
|
ExportSurfaceKind::DeclareType => {
|
||||||
SymbolKind::Struct | SymbolKind::Contract | SymbolKind::ErrorType => Namespace::Type,
|
match &meta.ty {
|
||||||
_ => Namespace::Value,
|
Some(PbsType::Contract(_)) => SymbolKind::Contract,
|
||||||
|
Some(PbsType::ErrorType(_)) => SymbolKind::ErrorType,
|
||||||
|
_ => SymbolKind::Struct,
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
namespace: key.kind.namespace(),
|
||||||
visibility: Visibility::Pub,
|
visibility: Visibility::Pub,
|
||||||
ty: meta.ty.clone(),
|
ty: meta.ty.clone(),
|
||||||
is_host: meta.is_host,
|
is_host: meta.is_host,
|
||||||
@ -245,31 +251,35 @@ pub fn compile_project(
|
|||||||
for (module_path, ms) in &module_symbols_map {
|
for (module_path, ms) in &module_symbols_map {
|
||||||
for sym in ms.type_symbols.symbols.values() {
|
for sym in ms.type_symbols.symbols.values() {
|
||||||
if sym.visibility == Visibility::Pub {
|
if sym.visibility == Visibility::Pub {
|
||||||
exports.insert(ExportKey {
|
if let Some(surface_kind) = ExportSurfaceKind::from_symbol_kind(sym.kind) {
|
||||||
module_path: module_path.clone(),
|
exports.insert(ExportKey {
|
||||||
symbol_name: sym.name.clone(),
|
module_path: module_path.clone(),
|
||||||
kind: sym.kind.clone(),
|
symbol_name: sym.name.clone(),
|
||||||
}, ExportMetadata {
|
kind: surface_kind,
|
||||||
func_idx: None,
|
}, ExportMetadata {
|
||||||
is_host: sym.is_host,
|
func_idx: None,
|
||||||
ty: sym.ty.clone(),
|
is_host: sym.is_host,
|
||||||
});
|
ty: sym.ty.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for sym in ms.value_symbols.symbols.values() {
|
for sym in ms.value_symbols.symbols.values() {
|
||||||
if sym.visibility == Visibility::Pub {
|
if sym.visibility == Visibility::Pub {
|
||||||
// Find func_idx if it's a function or service
|
if let Some(surface_kind) = ExportSurfaceKind::from_symbol_kind(sym.kind) {
|
||||||
let func_idx = vm_module.functions.iter().position(|f| f.name == sym.name).map(|i| i as u32);
|
// Find func_idx if it's a function or service
|
||||||
|
let func_idx = vm_module.functions.iter().position(|f| f.name == sym.name).map(|i| i as u32);
|
||||||
exports.insert(ExportKey {
|
|
||||||
module_path: module_path.clone(),
|
exports.insert(ExportKey {
|
||||||
symbol_name: sym.name.clone(),
|
module_path: module_path.clone(),
|
||||||
kind: sym.kind.clone(),
|
symbol_name: sym.name.clone(),
|
||||||
}, ExportMetadata {
|
kind: surface_kind,
|
||||||
func_idx,
|
}, ExportMetadata {
|
||||||
is_host: sym.is_host,
|
func_idx,
|
||||||
ty: sym.ty.clone(),
|
is_host: sym.is_host,
|
||||||
});
|
ty: sym.ty.clone(),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -359,7 +369,7 @@ mod tests {
|
|||||||
let vec2_key = ExportKey {
|
let vec2_key = ExportKey {
|
||||||
module_path: "src/main/modules".to_string(),
|
module_path: "src/main/modules".to_string(),
|
||||||
symbol_name: "Vec2".to_string(),
|
symbol_name: "Vec2".to_string(),
|
||||||
kind: SymbolKind::Struct,
|
kind: ExportSurfaceKind::DeclareType,
|
||||||
};
|
};
|
||||||
assert!(compiled.exports.contains_key(&vec2_key));
|
assert!(compiled.exports.contains_key(&vec2_key));
|
||||||
|
|
||||||
|
|||||||
@ -62,7 +62,7 @@ pub struct ImportSpecNode {
|
|||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||||
pub struct ServiceDeclNode {
|
pub struct ServiceDeclNode {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub vis: String, // "pub" | "mod"
|
pub vis: Option<String>, // "pub" | "mod"
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub extends: Option<String>,
|
pub extends: Option<String>,
|
||||||
pub members: Vec<Node>, // ServiceFnSig
|
pub members: Vec<Node>, // ServiceFnSig
|
||||||
@ -86,7 +86,7 @@ pub struct ParamNode {
|
|||||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||||
pub struct FnDeclNode {
|
pub struct FnDeclNode {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub vis: String,
|
pub vis: Option<String>,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub params: Vec<ParamNode>,
|
pub params: Vec<ParamNode>,
|
||||||
pub ret: Option<Box<Node>>,
|
pub ret: Option<Box<Node>>,
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
use crate::common::diagnostics::{Diagnostic, DiagnosticBundle, DiagnosticLevel};
|
use crate::common::diagnostics::{Diagnostic, DiagnosticBundle, DiagnosticLevel};
|
||||||
use crate::frontends::pbs::ast::*;
|
use crate::frontends::pbs::ast::*;
|
||||||
use crate::frontends::pbs::symbols::*;
|
use crate::frontends::pbs::symbols::*;
|
||||||
|
use crate::semantics::export_surface::ExportSurfaceKind;
|
||||||
|
|
||||||
pub struct SymbolCollector {
|
pub struct SymbolCollector {
|
||||||
type_symbols: SymbolTable,
|
type_symbols: SymbolTable,
|
||||||
@ -40,11 +41,14 @@ impl SymbolCollector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn collect_fn(&mut self, decl: &FnDeclNode) {
|
fn collect_fn(&mut self, decl: &FnDeclNode) {
|
||||||
let vis = match decl.vis.as_str() {
|
let vis = match decl.vis.as_deref() {
|
||||||
"pub" => Visibility::Pub,
|
Some("pub") => Visibility::Pub,
|
||||||
"mod" => Visibility::Mod,
|
Some("mod") => Visibility::Mod,
|
||||||
_ => Visibility::FilePrivate,
|
_ => Visibility::FilePrivate,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.check_export_eligibility(SymbolKind::Function, vis, decl.span);
|
||||||
|
|
||||||
let symbol = Symbol {
|
let symbol = Symbol {
|
||||||
name: decl.name.clone(),
|
name: decl.name.clone(),
|
||||||
kind: SymbolKind::Function,
|
kind: SymbolKind::Function,
|
||||||
@ -59,11 +63,13 @@ impl SymbolCollector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn collect_service(&mut self, decl: &ServiceDeclNode) {
|
fn collect_service(&mut self, decl: &ServiceDeclNode) {
|
||||||
let vis = match decl.vis.as_str() {
|
let vis = match decl.vis.as_deref() {
|
||||||
"pub" => Visibility::Pub,
|
Some("pub") => Visibility::Pub,
|
||||||
"mod" => Visibility::Mod,
|
_ => Visibility::Mod, // Defaults to Mod
|
||||||
_ => Visibility::FilePrivate, // Should not happen with valid parser
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.check_export_eligibility(SymbolKind::Service, vis, decl.span);
|
||||||
|
|
||||||
let symbol = Symbol {
|
let symbol = Symbol {
|
||||||
name: decl.name.clone(),
|
name: decl.name.clone(),
|
||||||
kind: SymbolKind::Service,
|
kind: SymbolKind::Service,
|
||||||
@ -89,6 +95,9 @@ impl SymbolCollector {
|
|||||||
"error" => SymbolKind::ErrorType,
|
"error" => SymbolKind::ErrorType,
|
||||||
_ => SymbolKind::Struct, // Default
|
_ => SymbolKind::Struct, // Default
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.check_export_eligibility(kind.clone(), vis, decl.span);
|
||||||
|
|
||||||
let symbol = Symbol {
|
let symbol = Symbol {
|
||||||
name: decl.name.clone(),
|
name: decl.name.clone(),
|
||||||
kind,
|
kind,
|
||||||
@ -148,4 +157,15 @@ impl SymbolCollector {
|
|||||||
span: Some(symbol.span),
|
span: Some(symbol.span),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_export_eligibility(&mut self, kind: SymbolKind, vis: Visibility, span: crate::common::spans::Span) {
|
||||||
|
if let Err(msg) = ExportSurfaceKind::validate_visibility(kind, vis) {
|
||||||
|
self.diagnostics.push(Diagnostic {
|
||||||
|
level: DiagnosticLevel::Error,
|
||||||
|
code: Some("E_SEMANTIC_EXPORT_RESTRICTION".to_string()),
|
||||||
|
message: msg,
|
||||||
|
span: Some(span),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -154,7 +154,7 @@ impl Parser {
|
|||||||
|
|
||||||
fn parse_top_level_decl(&mut self) -> Result<Node, DiagnosticBundle> {
|
fn parse_top_level_decl(&mut self) -> Result<Node, DiagnosticBundle> {
|
||||||
match self.peek().kind {
|
match self.peek().kind {
|
||||||
TokenKind::Fn => self.parse_fn_decl("file".to_string()),
|
TokenKind::Fn => self.parse_fn_decl(None),
|
||||||
TokenKind::Pub | TokenKind::Mod | TokenKind::Declare | TokenKind::Service => self.parse_decl(),
|
TokenKind::Pub | TokenKind::Mod | TokenKind::Declare | TokenKind::Service => self.parse_decl(),
|
||||||
TokenKind::Invalid(ref msg) => {
|
TokenKind::Invalid(ref msg) => {
|
||||||
let code = if msg.contains("Unterminated string") {
|
let code = if msg.contains("Unterminated string") {
|
||||||
@ -181,23 +181,14 @@ impl Parser {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match self.peek().kind {
|
match self.peek().kind {
|
||||||
TokenKind::Service => self.parse_service_decl(vis.unwrap_or_else(|| "pub".to_string())),
|
TokenKind::Service => self.parse_service_decl(vis),
|
||||||
TokenKind::Declare => self.parse_type_decl(vis),
|
TokenKind::Declare => self.parse_type_decl(vis),
|
||||||
TokenKind::Fn => {
|
TokenKind::Fn => self.parse_fn_decl(vis),
|
||||||
let vis_str = vis.unwrap_or_else(|| "file".to_string());
|
|
||||||
if vis_str == "pub" {
|
|
||||||
return Err(self.error_with_code(
|
|
||||||
"Functions cannot be public. They are always mod or file-private.",
|
|
||||||
Some("E_RESOLVE_VISIBILITY"),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
self.parse_fn_decl(vis_str)
|
|
||||||
}
|
|
||||||
_ => Err(self.error("Expected 'service', 'declare', or 'fn'")),
|
_ => Err(self.error("Expected 'service', 'declare', or 'fn'")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_service_decl(&mut self, vis: String) -> Result<Node, DiagnosticBundle> {
|
fn parse_service_decl(&mut self, vis: Option<String>) -> Result<Node, DiagnosticBundle> {
|
||||||
let start_span = self.consume(TokenKind::Service)?.span;
|
let start_span = self.consume(TokenKind::Service)?.span;
|
||||||
let name = self.expect_identifier()?;
|
let name = self.expect_identifier()?;
|
||||||
let mut extends = None;
|
let mut extends = None;
|
||||||
@ -362,7 +353,7 @@ impl Parser {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_fn_decl(&mut self, vis: String) -> Result<Node, DiagnosticBundle> {
|
fn parse_fn_decl(&mut self, vis: Option<String>) -> Result<Node, DiagnosticBundle> {
|
||||||
let start_span = self.consume(TokenKind::Fn)?.span;
|
let start_span = self.consume(TokenKind::Fn)?.span;
|
||||||
let name = self.expect_identifier()?;
|
let name = self.expect_identifier()?;
|
||||||
let params = self.parse_param_list()?;
|
let params = self.parse_param_list()?;
|
||||||
@ -1181,7 +1172,7 @@ fn good() {}
|
|||||||
let mut parser = Parser::new(source, 0);
|
let mut parser = Parser::new(source, 0);
|
||||||
let result = parser.parse_file().expect("mod fn should be allowed");
|
let result = parser.parse_file().expect("mod fn should be allowed");
|
||||||
if let Node::FnDecl(fn_decl) = &result.decls[0] {
|
if let Node::FnDecl(fn_decl) = &result.decls[0] {
|
||||||
assert_eq!(fn_decl.vis, "mod");
|
assert_eq!(fn_decl.vis, Some("mod".to_string()));
|
||||||
} else {
|
} else {
|
||||||
panic!("Expected FnDecl");
|
panic!("Expected FnDecl");
|
||||||
}
|
}
|
||||||
@ -1191,10 +1182,12 @@ fn good() {}
|
|||||||
fn test_parse_pub_fn() {
|
fn test_parse_pub_fn() {
|
||||||
let source = "pub fn test() {}";
|
let source = "pub fn test() {}";
|
||||||
let mut parser = Parser::new(source, 0);
|
let mut parser = Parser::new(source, 0);
|
||||||
let result = parser.parse_file();
|
let result = parser.parse_file().expect("pub fn should be allowed in parser");
|
||||||
assert!(result.is_err(), "pub fn should be disallowed");
|
if let Node::FnDecl(fn_decl) = &result.decls[0] {
|
||||||
let err = result.unwrap_err();
|
assert_eq!(fn_decl.vis, Some("pub".to_string()));
|
||||||
assert!(err.diagnostics[0].message.contains("Functions cannot be public"));
|
} else {
|
||||||
|
panic!("Expected FnDecl");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@ -3,14 +3,14 @@ use crate::frontends::pbs::types::PbsType;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum Visibility {
|
pub enum Visibility {
|
||||||
FilePrivate,
|
FilePrivate,
|
||||||
Mod,
|
Mod,
|
||||||
Pub,
|
Pub,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]
|
||||||
pub enum SymbolKind {
|
pub enum SymbolKind {
|
||||||
Function,
|
Function,
|
||||||
Service,
|
Service,
|
||||||
|
|||||||
@ -48,6 +48,7 @@ pub mod manifest;
|
|||||||
pub mod deps;
|
pub mod deps;
|
||||||
pub mod sources;
|
pub mod sources;
|
||||||
pub mod building;
|
pub mod building;
|
||||||
|
pub mod semantics;
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
|
|||||||
40
crates/prometeu-compiler/src/semantics/export_surface.rs
Normal file
40
crates/prometeu-compiler/src/semantics/export_surface.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
use crate::frontends::pbs::symbols::{SymbolKind, Visibility};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||||
|
pub enum ExportSurfaceKind {
|
||||||
|
Service,
|
||||||
|
DeclareType, // struct, storage struct, type alias
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExportSurfaceKind {
|
||||||
|
pub fn from_symbol_kind(kind: SymbolKind) -> Option<Self> {
|
||||||
|
match kind {
|
||||||
|
SymbolKind::Service => Some(ExportSurfaceKind::Service),
|
||||||
|
SymbolKind::Struct | SymbolKind::Contract | SymbolKind::ErrorType => {
|
||||||
|
Some(ExportSurfaceKind::DeclareType)
|
||||||
|
}
|
||||||
|
SymbolKind::Function | SymbolKind::Local => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn validate_visibility(kind: SymbolKind, vis: Visibility) -> Result<(), String> {
|
||||||
|
if vis == Visibility::Pub {
|
||||||
|
if Self::from_symbol_kind(kind).is_none() {
|
||||||
|
let kind_str = match kind {
|
||||||
|
SymbolKind::Function => "Functions",
|
||||||
|
_ => "This declaration",
|
||||||
|
};
|
||||||
|
return Err(format!("{} are not exportable in this version.", kind_str));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn namespace(&self) -> crate::frontends::pbs::symbols::Namespace {
|
||||||
|
match self {
|
||||||
|
ExportSurfaceKind::Service => crate::frontends::pbs::symbols::Namespace::Type,
|
||||||
|
ExportSurfaceKind::DeclareType => crate::frontends::pbs::symbols::Namespace::Type,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
crates/prometeu-compiler/src/semantics/mod.rs
Normal file
1
crates/prometeu-compiler/src/semantics/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod export_surface;
|
||||||
@ -67,7 +67,7 @@ fn test_integration_test01_link() {
|
|||||||
|
|
||||||
let mut vm = VirtualMachine::default();
|
let mut vm = VirtualMachine::default();
|
||||||
// Use initialize to load the ROM; entrypoint must be numeric or empty (defaults to 0)
|
// Use initialize to load the ROM; entrypoint must be numeric or empty (defaults to 0)
|
||||||
vm.initialize(unit.rom, "").expect("Failed to initialize VM");
|
vm.initialize(unit.rom, "frame").expect("Failed to initialize VM");
|
||||||
|
|
||||||
let mut native = SimpleNative;
|
let mut native = SimpleNative;
|
||||||
let mut hw = SimpleHardware::new();
|
let mut hw = SimpleHardware::new();
|
||||||
|
|||||||
@ -6,7 +6,6 @@ use prometeu_core::virtual_machine::{LogicalFrameEndingReason, VirtualMachine};
|
|||||||
use prometeu_core::Hardware;
|
use prometeu_core::Hardware;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use prometeu_bytecode::BytecodeLoader;
|
|
||||||
|
|
||||||
struct MockNative;
|
struct MockNative;
|
||||||
impl NativeInterface for MockNative {
|
impl NativeInterface for MockNative {
|
||||||
@ -40,7 +39,6 @@ fn test_canonical_cartridge_heartbeat() {
|
|||||||
let pbc_bytes = fs::read(pbc_path).expect("Failed to read canonical PBC. Did you run the generation test?");
|
let pbc_bytes = fs::read(pbc_path).expect("Failed to read canonical PBC. Did you run the generation test?");
|
||||||
|
|
||||||
// Determine entrypoint from the compiled module exports
|
// Determine entrypoint from the compiled module exports
|
||||||
let module = BytecodeLoader::load(&pbc_bytes).expect("Failed to parse PBC");
|
|
||||||
let entry_symbol = "src/main/modules:frame";
|
let entry_symbol = "src/main/modules:frame";
|
||||||
|
|
||||||
let mut vm = VirtualMachine::new(vec![], vec![]);
|
let mut vm = VirtualMachine::new(vec![], vec![]);
|
||||||
|
|||||||
@ -641,7 +641,7 @@
|
|||||||
"start": 739,
|
"start": 739,
|
||||||
"end": 788
|
"end": 788
|
||||||
},
|
},
|
||||||
"vis": "file",
|
"vis": null,
|
||||||
"name": "add",
|
"name": "add",
|
||||||
"params": [
|
"params": [
|
||||||
{
|
{
|
||||||
@ -743,7 +743,7 @@
|
|||||||
"start": 790,
|
"start": 790,
|
||||||
"end": 1180
|
"end": 1180
|
||||||
},
|
},
|
||||||
"vis": "file",
|
"vis": null,
|
||||||
"name": "frame",
|
"name": "frame",
|
||||||
"params": [],
|
"params": [],
|
||||||
"ret": {
|
"ret": {
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user