How houssameddine-yousfi/justcompiler works
1. What this repository is
- This is not a traditional code-generating compiler yet; it is an interpreted language implementation for the “Just” JVM language.
- The architecture is a classic compiler front end plus evaluator: source text → tokens → syntax tree → bound tree → execution result.
2. Top-level orchestration
- Compilation, SyntaxTree, Evaluator, EvaluationResult, and Index form the main execution path.
- The driver/REPL behavior described in the README appears to be coordinated at the top level, likely through Index, which feeds user input into the compilation pipeline and prints either results or diagnostics.
3. Text and source management
- The Text package (SourceText, TextLine, TextSpan) models the original input and exact source locations.
- This layer exists primarily to support accurate diagnostics, including line/column spans and highlighted error messages.
4. Lexical analysis
- Syntax/Lexer converts raw source text into SyntaxToken objects.
- SyntaxKind and SyntaxFacts define the language vocabulary: keywords, operators, punctuation, literals, and precedence/associativity rules.
- This layer is responsible for turning malformed text into recoverable lexer diagnostics rather than failing outright.
5. Parsing and syntax tree
- Syntax/Parser builds the concrete syntax tree rooted at CompilationUnitSyntax.
- The syntax layer includes expression and statement nodes for:
- literals, names, unary/binary expressions, parenthesized expressions
- assignments and variable declarations
- blocks, if/else, while, and for
- SyntaxNode, ExpressionSyntax, StatementSyntax, and the specific syntax classes define the tree structure used before semantic analysis.
6. Semantic binding
- The Binding package lowers syntax into a typed, semantically valid bound tree.
- Binder resolves names, checks operator applicability, enforces scope rules, and converts syntax into Bound* nodes.
- BoundScope, BoundGlobalScope, and VariableSymbol model declaration visibility, read-only variables, and shadowing/redeclaration rules.
- BoundBinaryOperator, BoundUnaryOperator, and their Kind enums encode the supported operator/type combinations.
7. Runtime evaluation
- Evaluator executes the bound tree and produces the final value for an expression or statement block.
- Bound node types such as BoundBlockStatement, BoundIfStatment, BoundWhileStatement, BoundForStatement, BoundVariableDeclaration, and BoundAssignmentExpression represent the executable form.
- The language is currently value-oriented: the result of a block is the last expression/value produced.
8. Diagnostics as a first-class subsystem
- Diagnostic and DiagnosticsBag accumulate errors across lexing, parsing, binding, and evaluation phases.
- This is a key boundary in the architecture: syntax errors, type errors, undefined variables, and scope violations are all reported through the same diagnostic channel.
- The README’s highlighted error spans are enabled by the Text layer plus these diagnostic classes.
9. Language model and supported semantics
- The repo supports integers and booleans only.
- Operators include arithmetic, equality/inequality, comparison, and logical negation.
- Control flow includes if/else, while, for, and block scoping.
- Variables can be declared mutable (var) or read-only (const), with scoping preventing invalid redeclarations or out-of-scope access.
10. Testing structure
- Tests are split by subsystem, which mirrors the architecture:
- Syntax/LexerTest, Syntax/ParserTest, Syntax/SyntaxFactsTest
- EvaluationTest
- Text/SourceTextTest
- This indicates the repo is organized around validating each compiler phase independently, which is useful when drawing the architecture diagram.
11. Build/runtime environment
- The project is built with Maven and targets Java 17+.
- There are no external services or infrastructure dependencies; the system is self-contained and runs entirely on the JVM.
12. Best diagram boundary
- A clear architecture diagram should show four main layers:
- Input/Text handling
- Syntax processing
- Binding/semantic analysis
- Evaluation/runtime
- Diagnostics should be drawn as a cross-cutting concern spanning all layers.
Main entry points: Binder.java Binder · Compilation.java Compilation · SyntaxTree.java Syntax Tree · Lexer.java Lexer
Components 20
Orchestration
Entry point and compilation flow.
- Index · Interactive entry point that accepts input and prints results or diagnostics.
src/main/java/com/JsonAjax/justcompiler/Index.java - Compilation · Coordinates syntax analysis, binding, and evaluation for a submission.
src/main/java/com/JsonAjax/justcompiler/Compilation.java - Diagnostics · Collects errors across lexing, parsing, binding, and evaluation.
src/main/java/com/JsonAjax/justcompiler/DiagnosticsBag.java - Diagnostic · Represents a single reported problem with source context.
src/main/java/com/JsonAjax/justcompiler/Diagnostic.java
Text
Source text and location tracking.
- Source Text · Stores source input with line and span mapping for diagnostics.
src/main/java/com/JsonAjax/justcompiler/Text/SourceText.java - Text Span · Represents highlighted source ranges used in error reporting.
src/main/java/com/JsonAjax/justcompiler/Text/TextSpan.java - Text Line · Tracks line boundaries and offsets in the original source.
src/main/java/com/JsonAjax/justcompiler/Text/TextLine.java
Syntax
Lexing, parsing, and concrete syntax tree.
- Syntax Tree · Wraps parsing into a tree usable by later phases.
src/main/java/com/JsonAjax/justcompiler/Syntax/SyntaxTree.java - Lexer · Converts source text into syntax tokens and lexer diagnostics.
src/main/java/com/JsonAjax/justcompiler/Syntax/Lexer.java - Parser · Builds the compilation unit syntax tree from tokens.
src/main/java/com/JsonAjax/justcompiler/Syntax/Parser.java - Syntax Facts · Defines keywords, operators, precedence, and token metadata.
src/main/java/com/JsonAjax/justcompiler/Syntax/SyntaxFacts.java - Syntax Nodes · Expression and statement node hierarchy for the parsed language.
src/main/java/com/JsonAjax/justcompiler/Syntax/SyntaxNode.java
Binding
Semantic analysis and bound tree.
- Binder · Resolves names, checks operators, and lowers syntax to bound nodes.
src/main/java/com/JsonAjax/justcompiler/Binding/Binder.java - Bound Scope · Tracks variable visibility, shadowing, and redeclaration rules.
src/main/java/com/JsonAjax/justcompiler/Binding/BoundScope.java - Global Scope · Holds the top-level bound declarations for a compilation.
src/main/java/com/JsonAjax/justcompiler/Binding/BoundGlobalScope.java - Variable Symbol · Describes variables, including name, type, and mutability.
src/main/java/com/JsonAjax/justcompiler/VariableSymbol.java - Bound Ops · Defines supported unary and binary operator bindings.
src/main/java/com/JsonAjax/justcompiler/Binding/BoundBinaryOperator.java - Bound Nodes · Executable semantic node hierarchy for expressions and statements.
src/main/java/com/JsonAjax/justcompiler/Binding/BoundNode.java
Runtime
Execution of bound nodes.
- Evaluator · Executes bound statements and expressions to produce a value.
src/main/java/com/JsonAjax/justcompiler/Evaluator.java - Eval Result · Carries the computed value and any diagnostics from execution.
src/main/java/com/JsonAjax/justcompiler/EvaluationResult.java
Connections 25
- Index → Compilation: runs · The driver creates and executes compilations for user input.
- Compilation → Syntax Tree: parses · Compilation starts by turning source text into a syntax tree.
- Syntax Tree → Lexer: uses · Tree construction depends on lexical tokenization.
- Syntax Tree → Parser: uses · Tree construction depends on parsing.
- Lexer → Source Text: reads · Lexing consumes the original source text.
- Lexer → Syntax Facts: consults · Tokenization and precedence decisions use language facts.
- Parser → Syntax Nodes: builds · The parser creates concrete syntax nodes.
- Parser → Syntax Facts: consults · Parsing uses token kinds and precedence rules.
- Source Text → Text Line: maps · Source text is segmented into lines for diagnostics.
- Source Text → Text Span: supports · Span locations reference positions within source text.
- Syntax Tree → Diagnostics: reports · Syntax tree creation collects parse diagnostics.
- Lexer → Diagnostics: reports · Lexical errors are accumulated as diagnostics.
- Parser → Diagnostics: reports · Parsing errors are accumulated as diagnostics.
- Compilation → Binder: binds · Compilation lowers syntax to semantically checked bound nodes.
- Binder → Bound Scope: uses · The binder manages nested scopes and symbol visibility.
- Binder → Global Scope: produces · Binding produces the top-level scope snapshot.
- Binder → Variable Symbol: declares · Variables are represented as symbols during binding.
- Binder → Bound Ops: matches · Operator applicability is resolved through operator tables.
- Binder → Bound Nodes: creates · Syntax is lowered into bound statements and expressions.
- Bound Scope → Variable Symbol: contains · Scopes store declared variables.
- Compilation → Evaluator: executes · Compilation hands the bound tree to the evaluator.
- Evaluator → Bound Nodes: walks · Execution traverses the bound tree.
- Evaluator → Eval Result: returns · Evaluation produces a final result wrapper.
- Evaluator → Diagnostics: reports · Runtime and semantic failures surface through diagnostics.
- Eval Result → Diagnostic: contains · The result wrapper can carry reported issues.