Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions src/ast/unit.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::ast::EventDecl;
use crate::ir::ctx::CtxMethod;
use crate::parser::SourceLoc;

Expand All @@ -9,6 +10,7 @@ pub struct Unit {
pub sections: Vec<String>,
pub kind: ProgramKind,
pub license: Option<String>,
pub events: Vec<EventDecl>,
pub body: Vec<Stmt>,
}

Expand Down Expand Up @@ -122,8 +124,10 @@ pub enum ExprKind {
SizeOf {
name: String,
},


FieldAccess {
base: Box<Expr>,
field: String,
},
}

#[derive(Debug, Clone)]
Expand All @@ -148,7 +152,7 @@ pub struct HeapLookup {

#[derive(Debug, Clone)]
pub struct MethodCall {
pub receiver: String,
pub receiver: Box<Expr>,
pub method: String,
pub arg: Vec<Expr>,
}
Expand Down Expand Up @@ -202,7 +206,13 @@ impl ProgramKind {

ProgramKind::Socket => &[LoadU8, LoadU16, LoadU32],

ProgramKind::Kprobe => &[LoadU64, GetPidTgid, GetUidGid],
ProgramKind::Kprobe => &[
LoadU64,
GetPidTgid,
GetUidGid,
ProbeReadUserStr,
ProbeReadKernelStr,
],

ProgramKind::Tracepoint => &[
LoadU8,
Expand All @@ -218,9 +228,11 @@ impl ProgramKind {
GetCurrentComm,
GetCurrentTask,
GetKtimeNs,
ProbeReadUserStr,
ProbeReadKernelStr,
],

ProgramKind::RawTracepoint => &[LoadU64],
ProgramKind::RawTracepoint => &[LoadU64, ProbeReadUserStr, ProbeReadKernelStr],

ProgramKind::Fentry | ProgramKind::Fexit => &[LoadU64],

Expand Down
84 changes: 58 additions & 26 deletions src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,26 +48,27 @@ impl ErrorHandler {
.build(span, &self.source_manager)
}

// Create a lexical error diagnostic
// pub fn lexical_error(
// &self,
// code: ErrorCode,
// message: impl Into<String>,
// span: &Span,
// ) -> Result<CompileDiagnostic, String> {
// DiagnosticBuilder::new(ErrorCategory::Lexical, code, message)
// .build(span, &self.source_manager)
// }

// Create a codegen error diagnostic
// pub fn codegen_error(
// &self,
// message: impl Into<String>,
// span: &Span,
// ) -> Result<CompileDiagnostic, String> {
// DiagnosticBuilder::new(ErrorCategory::Codegen, ErrorCode::CodegenError, message)
// .build(span, &self.source_manager)
// }
/// Create a lexical error diagnostic
pub fn lexical_error(
&self,
code: ErrorCode,
message: impl Into<String>,
span: &Span,
) -> Result<CompileDiagnostic, String> {
DiagnosticBuilder::new(ErrorCategory::Lexical, code, message)
.build(span, &self.source_manager)
}

/// Create a codegen error diagnostic
pub fn codegen_error(
&self,
message: impl Into<String>,
span: &Span,
) -> Result<CompileDiagnostic, String> {
DiagnosticBuilder::new(ErrorCategory::Codegen, ErrorCode::CodegenError, message)
.build(span, &self.source_manager)
}

}

pub fn compile(input_path: &Path, _output_path: &Path) -> Result<(), miette::Report> {
Expand Down Expand Up @@ -105,7 +106,24 @@ pub fn compile(input_path: &Path, _output_path: &Path) -> Result<(), miette::Rep
Ok(prog) => prog,
Err(e) => {
let span = Span::new(_file_id, e.0.offset..e.0.offset + 1);
match error_handler.parse_error(e.1.clone(), &span) {

let error_result = if e.1.contains("Invalid character")
|| e.1.contains("Unterminated")
|| e.1.contains("Invalid escape sequence")
|| e.1.contains("Unexpected character") {
let code = match e.1.as_str() {
msg if msg.contains("Invalid character") => ErrorCode::InvalidCharacter,
msg if msg.contains("Unterminated comment") => ErrorCode::UnterminatedComment,
msg if msg.contains("Unterminated string") => ErrorCode::UnterminatedString,
msg if msg.contains("Invalid escape sequence") => ErrorCode::InvalidEscapeSequence,
_ => ErrorCode::InvalidCharacter,
};
error_handler.lexical_error(code, e.1.clone(), &span)
} else {
error_handler.parse_error(e.1.clone(), &span)
};

match error_result {
Ok(diag) => {
let report = error_handler.report_error(diag);
eprintln!("{}", report);
Expand All @@ -119,8 +137,7 @@ pub fn compile(input_path: &Path, _output_path: &Path) -> Result<(), miette::Rep
}
}
};

// Run semantic analysis and emit a CompileDiagnostic with source span on error

if let Err(sem_err) = crate::sema::check_program(&program) {
use crate::diagnostics::ErrorCode;
use crate::parser::SourceLoc;
Expand Down Expand Up @@ -258,9 +275,24 @@ pub fn compile(input_path: &Path, _output_path: &Path) -> Result<(), miette::Rep
.map_err(|e| miette::miette!("{:?}", e))
.wrap_err("Lowering failed")?;

crate::emit::ebpf_c::program::emit_program(&program_ir, &output)
.map_err(|e| miette::miette!("{}", e))
.wrap_err("Emit failed")?;
// Emit eBPF code with stage-aware error handling
if let Err(e) = crate::emit::ebpf_c::program::emit_program(&program_ir, &output) {
let span = Span::new(_file_id, 0..1);
let error_msg = format!("Code generation failed: {}", e);

match error_handler.codegen_error(error_msg.clone(), &span) {
Ok(diag) => {
let report = error_handler.report_error(diag);
eprintln!("{}", report);
return Err(report);
}
Err(_) => {
let report = miette::miette!("{}", error_msg);
eprintln!("{}", report);
return Err(report);
}
}
}

Ok(())
}
46 changes: 42 additions & 4 deletions src/diagnostics/category.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,34 @@
//! Error categories for the Solnix compiler
//!
//! Each error is classified into one of these categories to help users
//! understand where in the compilation pipeline the error occurred.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ErrorType {
/// Invalid token or lexical error (from Lexer stage)
InvalidToken,
/// Syntax error (from Parser stage)
SyntaxError,
/// Type error or semantic error (from Semantic stage)
TypeError,
/// Internal error from IR/Codegen stage
InternalError,
/// I/O error
IoError,
}

impl ErrorType {
pub fn as_str(&self) -> &'static str {
match self {
Self::InvalidToken => "Invalid token",
Self::SyntaxError => "Syntax error",
Self::TypeError => "Type error",
Self::InternalError => "Internal error",
Self::IoError => "I/O error",
}
}
}

impl std::fmt::Display for ErrorType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ErrorCategory {
Expand Down Expand Up @@ -30,6 +57,17 @@ impl ErrorCategory {
Self::Io => "I/O",
}
}

/// Map compilation stage category to a clean, user-friendly error type
pub fn to_error_type(&self) -> ErrorType {
match self {
Self::Lexical => ErrorType::InvalidToken,
Self::Parse => ErrorType::SyntaxError,
Self::Semantic => ErrorType::TypeError,
Self::Codegen | Self::Optimizer => ErrorType::InternalError,
Self::Io => ErrorType::IoError,
}
}
}

impl std::fmt::Display for ErrorCategory {
Expand Down
11 changes: 9 additions & 2 deletions src/diagnostics/diagnostic.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use super::category::ErrorCategory;
use super::category::{ErrorCategory, ErrorType};
use super::error_code::ErrorCode;
use super::source_manager::{Span, SourceManager};
use miette::{Diagnostic, SourceSpan};
use thiserror::Error;

#[derive(Error, Debug, Diagnostic)]
#[error("{category} error: {code}\n {message}")]
#[error("{error_type}: {code}\n {message}")]
pub struct CompileDiagnostic {
#[source_code]
pub file_content: String,
Expand All @@ -15,6 +15,7 @@ pub struct CompileDiagnostic {

pub code: String,
pub category: ErrorCategory,
pub error_type: ErrorType,
pub message: String,
pub label_message: String,
}
Expand All @@ -37,6 +38,11 @@ impl DiagnosticBuilder {
}
}

pub fn with_label(mut self, label: impl Into<String>) -> Self {
self.label_message = Some(label.into());
self
}

pub fn build(
self,
span: &Span,
Expand All @@ -56,6 +62,7 @@ impl DiagnosticBuilder {
span: span.to_source_span(),
code: self.code.code(),
category: self.category,
error_type: self.category.to_error_type(),
message: self.message,
label_message,
})
Expand Down
2 changes: 1 addition & 1 deletion src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub mod error_code;
pub mod source_manager;

// Re-export commonly used types
pub use category::ErrorCategory;
pub use category::{ErrorCategory, ErrorType};
pub use diagnostic::{CompileDiagnostic, DiagnosticBuilder};
pub use error_code::ErrorCode;
pub use source_manager::{FileId, Span, SourceManager};
Loading