sphinx/
lib.rs

1// disable these until we have a working system
2#![allow(dead_code)]
3// #![allow(unused_imports)]
4#![feature(ptr_metadata)]
5
6use std::io;
7
8#[macro_use]
9mod macros;
10
11pub mod utils;
12
13pub mod source;
14pub mod lexer;
15pub mod parser;
16
17pub mod language;
18pub mod codegen;
19pub mod runtime;
20pub mod builtins;
21
22pub mod frontend;
23pub mod debug;
24
25
26use source::{SourceText, ModuleSource, ParseContext};
27use parser::ParserError;
28use parser::stmt::StmtMeta;
29use codegen::{CompiledProgram, Compiler, CompileError};
30use runtime::strings::StringInterner;
31
32#[derive(Debug)]
33pub enum BuildErrors {
34    // depending on which stage the build failed
35    Source(io::Error),
36    Syntax(Box<[ParserError]>),
37    Compile(Box<[CompileError]>),
38}
39
40pub fn build_module(source: &ModuleSource) -> Result<CompiledProgram, BuildErrors> {
41    let source_text = source.read_text()
42        .map_err(BuildErrors::Source)?;
43    
44    build_source(source_text)
45}
46
47pub fn build_source(source_text: SourceText) -> Result<CompiledProgram, BuildErrors> {
48    let mut interner = StringInterner::new();
49    
50    // parsing
51    let parse_result = parse_source(&mut interner, source_text);
52    
53    if let Err(errors) = parse_result {
54        return Err(BuildErrors::Syntax(errors.into_boxed_slice()));
55    }
56    
57    // compilation
58    let compile_result = compile_ast(interner, parse_result.unwrap());
59    
60    if let Err(errors) = compile_result {
61        return Err(BuildErrors::Compile(errors.into_boxed_slice()));
62    }
63    
64    Ok(compile_result.unwrap())
65}
66
67
68
69/// Produce AST from SourceText
70pub fn parse_source(interner: &mut StringInterner, source_text: SourceText) -> Result<Vec<StmtMeta>, Vec<ParserError>> {
71    let lexer_factory = language::create_default_lexer_rules();
72    let mut parse_ctx = ParseContext::new(&lexer_factory, interner);
73    
74    parse_ctx.parse_ast(source_text)
75}
76
77/// Produce bytecode from AST
78pub fn compile_ast(interner: StringInterner, ast: Vec<StmtMeta>) -> Result<CompiledProgram, Vec<CompileError>> {
79    let compiler = Compiler::new(interner);
80    compiler.compile_program(ast.iter())
81}
82
83
84pub fn print_build_errors(errors: &BuildErrors, source: &ModuleSource) {
85    match errors {
86        BuildErrors::Source(error) => {
87            println!("Error reading source: {}.", error);
88        }
89        
90        BuildErrors::Syntax(errors) => {
91            println!("Errors in {}:\n", source);
92            frontend::print_source_errors(source, errors);
93        }
94        
95        BuildErrors::Compile(errors) => {
96            println!("Errors in {}:\n", source);
97            frontend::print_source_errors(source, errors);
98        }
99    }
100    
101}