Skip to content

Commit 48715e2

Browse files
committed
Migrate: Replace BCEL with ASM completely!
- BCEL dependencies are removed Thanks to Claude Code!
1 parent 8141f7a commit 48715e2

27 files changed

+2902
-3399
lines changed

.claude/settings.local.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(find:*)",
5+
"Bash(java:*)",
6+
"Bash(sbt clean:*)",
7+
"Bash(rm:*)",
8+
"Bash(sbt:*)",
9+
"Bash(grep:*)",
10+
"Bash(mv:*)",
11+
"Bash(ls:*)",
12+
"Bash(cat:*)",
13+
"Bash(timeout 30 sbt 'testOnly *CountersSpec')"
14+
],
15+
"deny": []
16+
}
17+
}

CLAUDE.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Build Commands
6+
7+
- **Build the project**: `sbt compile`
8+
- **Run tests**: `sbt test`
9+
- **Run a single test**: `sbt 'testOnly *HelloWorldSpec'`
10+
- **Package JAR**: `sbt assembly` or `sbt packageBin`
11+
- **Create distribution**: `sbt dist` (creates a distribution zip in target/dist)
12+
- **Run a script**: `sbt 'runScript <script.on> [args]'`
13+
- **Clean**: `sbt clean`
14+
15+
## High-Level Architecture
16+
17+
The Onion compiler follows a pipeline architecture with distinct phases:
18+
19+
1. **Parsing** (`Parsing.scala`) - Uses JavaCC-generated parser (`JJOnionParser.jj`) to create untyped AST
20+
2. **Rewriting** (`Rewriting.scala`) - Transforms and normalizes the AST
21+
3. **Type Checking** (`Typing.scala`) - Produces typed AST from untyped AST
22+
4. **Code Generation** (`TypedGenerating.scala`) - Generates JVM bytecode from typed AST
23+
- Currently transitioning from BCEL to ASM for bytecode generation
24+
- `AsmCodeGeneration.scala` contains the new ASM-based backend
25+
26+
### Key Components
27+
28+
- **Processor Pipeline**: Compiler phases extend `Processor[A,B]` trait and can be composed with `andThen`
29+
- **AST Types**:
30+
- Untyped AST in `AST.scala`
31+
- Typed AST in `TypedAST.scala`
32+
- **Entry Points**:
33+
- `onion.tools.CompilerFrontend` - Main compiler executable (`onionc`)
34+
- `onion.tools.ScriptRunner` - Script execution (`onion`)
35+
- `onion.tools.Shell` - Interactive shell/REPL
36+
- **Error Handling**: `SemanticError`, `CompileError`, and `SemanticErrorReporter` for compilation diagnostics
37+
38+
### Testing
39+
40+
Tests use ScalaTest and extend `AbstractShellSpec` for integration testing. Test files are in `src/test/scala/onion/compiler/tools/`.
41+
42+
### Language Features
43+
44+
Onion is a statically-typed, object-oriented language that compiles to JVM bytecode. Key features include:
45+
- Classes with public/private visibility modifiers
46+
- Static and instance methods
47+
- Type inference
48+
- First-class functions (Function0 through Function10 interfaces)
49+
- Module system with imports

README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,21 @@ compiles into JVM class files as in-memory or real files.
66
Originally, Onion was written in Java. It has been rewritten in Scala completely except Parser,
77
using JavaCC.
88

9+
## Architecture
10+
11+
The compiler parses source code into an untyped AST and then performs type
12+
checking to produce a **typed AST**. The old intermediate representation (IRT)
13+
has been folded into this typed tree. Code generation now runs on the typed
14+
AST via a thin compatibility layer using ASM.
15+
916
## Tools
1017

1118
### onionc
1219

1320
#### Usage
1421

15-
```
16-
onionc [options] source files...
22+
```txt
23+
onionc [options] source files...
1724
```
1825

1926
#### Available options:

bin/onion

100644100755
Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,33 @@
11
#!/bin/sh
22

3-
# This variable represents the directory in which Onion is installed.
4-
# ONION_HOME=
3+
# Use java from PATH if JAVA_HOME is not set
4+
if [ -z "$JAVA_HOME" ]; then
5+
JAVA_CMD="java"
6+
else
7+
JAVA_CMD="$JAVA_HOME/bin/java"
8+
fi
59

6-
# This variable represents the directory in which J2SE is installed.
7-
# JAVA_HOME=
10+
# Check if java is available
11+
if ! command -v "$JAVA_CMD" > /dev/null 2>&1; then
12+
echo "Error: Java not found. Please install Java or set JAVA_HOME environment variable."
13+
exit 1
14+
fi
815

9-
if [ $JAVA_HOME/ = / ]
10-
then
11-
echo Please set the environment variable JAVA_HOME.
12-
exit
16+
# Build classpath with all jars in lib directory
17+
CLASSPATH="$ONION_HOME/onion.jar"
18+
if [ -d "$ONION_HOME/lib" ]; then
19+
for jar in "$ONION_HOME/lib"/*.jar; do
20+
if [ -f "$jar" ]; then
21+
CLASSPATH="$CLASSPATH:$jar"
22+
fi
23+
done
1324
fi
1425

15-
if [ $ONION_HOME/ = / ]
16-
then
17-
echo Please set the environment variable ONION_HOME.
18-
exit
26+
# Add user classpath if set
27+
if [ -n "$CLASSPATH" ]; then
28+
CLASSPATH="$CLASSPATH:$CLASSPATH"
1929
fi
30+
echo $CLASSPATH
2031

21-
$JAVA_HOME/bin/java -classpath $CLASSPATH:$ONION_HOME/onion.jar:$ONION_HOME/onion-library.jar:$ONION_HOME/lib/bcel.jar onion.tools.ScriptRunner $@
32+
# Run the Onion script runner
33+
exec "$JAVA_CMD" -classpath "$CLASSPATH" onion.tools.ScriptRunner "$@"

bin/onion.bat

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,35 @@
11
@echo off
2-
3-
rem This variable represents the directory in which Onion is installed.
4-
rem set ONION_HOME=
5-
6-
rem This variable represents the directory in which J2SE is installed.
7-
rem set JAVA_HOME=$JAVA_HOME$
8-
9-
if /i %ONION_HOME%/ == / goto NO_ONION_HOME
10-
11-
if /i %JAVA_HOME%/ == / goto NO_JAVA_HOME
12-
13-
goto START
14-
15-
:NO_JAVA_HOME
16-
echo Please set the environment variable JAVA_HOME
17-
goto END
18-
19-
:NO_ONION_HOME
20-
echo Please set the environment variable ONION_HOME
21-
goto END
22-
23-
:START
24-
%JAVA_HOME%\bin\java -classpath %CLASSPATH%;%ONION_HOME%\onion.jar;%ONION_HOME%\lib\bcel.jar;%ONION_HOME%\onion-library.jar onion.tools.ScriptRunner %*
25-
26-
:END
2+
setlocal enabledelayedexpansion
3+
4+
rem Remove trailing backslash from ONION_HOME if present
5+
if "%ONION_HOME:~-1%"=="\" set "ONION_HOME=%ONION_HOME:~0,-1%"
6+
7+
rem Use java from PATH if JAVA_HOME is not set
8+
if defined JAVA_HOME (
9+
set "JAVA_CMD=%JAVA_HOME%\bin\java"
10+
) else (
11+
set "JAVA_CMD=java"
12+
)
13+
14+
rem Check if java is available
15+
"%JAVA_CMD%" -version >nul 2>&1
16+
if errorlevel 1 (
17+
echo Error: Java not found. Please install Java or set JAVA_HOME environment variable.
18+
exit /b 1
19+
)
20+
21+
rem Build classpath with all jars in lib directory
22+
set "CP=%ONION_HOME%\onion.jar"
23+
if exist "%ONION_HOME%\lib" (
24+
for %%F in ("%ONION_HOME%\lib\*.jar") do (
25+
set "CP=!CP!;%%F"
26+
)
27+
)
28+
29+
rem Add user classpath if set
30+
if defined CLASSPATH (
31+
set "CP=%CP%;%CLASSPATH%"
32+
)
33+
34+
rem Run the Onion script runner
35+
"%JAVA_CMD%" -classpath "%CP%" onion.tools.ScriptRunner %*

bin/onionc

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
#!/bin/sh
22

3-
# This variable represents the directory in which Onion is installed.
4-
# ONION_HOME=
5-
6-
# This variable represents the directory in which J2SE is installed.
7-
# JAVA_HOME=
8-
9-
if [ $JAVA_HOME/ = / ]
10-
then
11-
echo Please set the environment variable JAVA_HOME.
12-
exit
3+
# Use java from PATH if JAVA_HOME is not set
4+
if [ -z "$JAVA_HOME" ]; then
5+
JAVA_CMD="java"
6+
else
7+
JAVA_CMD="$JAVA_HOME/bin/java"
138
fi
149

15-
if [ $ONION_HOME/ = / ]
16-
then
17-
echo Please set the environment variable ONION_HOME.
18-
exit
10+
# Check if java is available
11+
if ! command -v "$JAVA_CMD" > /dev/null 2>&1; then
12+
echo "Error: Java not found. Please install Java or set JAVA_HOME environment variable."
13+
exit 1
1914
fi
2015

21-
$JAVA_HOME/bin/java -jar $ONION_HOME/onion.jar $@
16+
# Run the Onion compiler
17+
exec "$JAVA_CMD" -jar "$ONION_HOME/onion.jar" "$@"

bin/onionc.bat

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,21 @@
11
@echo off
22

3-
rem This variable represents the directory in which Onion is installed.
4-
rem set ONION_HOME=
5-
6-
rem This variable represents the directory in which J2SE is installed.
7-
rem set JAVA_HOME=$JAVA_HOME$
8-
9-
if /i %ONION_HOME%/ == / goto NO_ONION_HOME
10-
11-
if /i %JAVA_HOME%/ == / goto NO_JAVA_HOME
12-
13-
goto START
14-
15-
:NO_JAVA_HOME
16-
echo Please set the environment variable JAVA_HOME
17-
goto END
18-
19-
:NO_ONION_HOME
20-
echo Please set the environment variable ONION_HOME
21-
goto END
22-
23-
:START
24-
%JAVA_HOME%\bin\java -jar %ONION_HOME%\onion.jar %*
25-
26-
:END
3+
rem Remove trailing backslash from ONION_HOME if present
4+
if "%ONION_HOME:~-1%"=="\" set "ONION_HOME=%ONION_HOME:~0,-1%"
5+
6+
rem Use java from PATH if JAVA_HOME is not set
7+
if defined JAVA_HOME (
8+
set "JAVA_CMD=%JAVA_HOME%\bin\java"
9+
) else (
10+
set "JAVA_CMD=java"
11+
)
12+
13+
rem Check if java is available
14+
"%JAVA_CMD%" -version >nul 2>&1
15+
if errorlevel 1 (
16+
echo Error: Java not found. Please install Java or set JAVA_HOME environment variable.
17+
exit /b 1
18+
)
19+
20+
rem Run the Onion compiler
21+
"%JAVA_CMD%" -jar "%ONION_HOME%\onion.jar" %*

build.sbt

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,12 @@ lazy val onionSettings = Seq(
7878
(Seq((Compile / javaSource).value) ++ Seq((Compile / scalaSource).value) ++ Seq((Compile / sourceManaged).value))
7979
},
8080
scalacOptions ++= Seq("-encoding", "utf8", "-unchecked", "-deprecation", "-feature", "-language:implicitConversions", "-language:existentials"),
81-
javacOptions ++= Seq("-sourcepath", "src.lib", "-Xlint:unchecked", "-source", "21"),
81+
javacOptions ++= Seq("-sourcepath", "src.lib", "-Xlint:unchecked", "-source", "17"),
8282
libraryDependencies ++= Seq(
83-
"org.apache.bcel" % "bcel" % "6.0",
84-
"org.ow2.asm" % "asm" % "5.0.2",
83+
"org.ow2.asm" % "asm" % "9.8",
84+
"org.ow2.asm" % "asm-commons" % "9.8",
85+
"org.ow2.asm" % "asm-tree" % "9.8",
86+
"org.ow2.asm" % "asm-util" % "9.8",
8587
"net.java.dev.javacc" % "javacc" % "5.0",
8688
"junit" % "junit" % "4.7" % "test",
8789
"org.scalatest" %% "scalatest" % "3.2.19" % "test"
@@ -120,7 +122,13 @@ lazy val onionSettings = Seq(
120122
target.value / "dist"
121123
},
122124
mainClass := Some("onion.tools.CompilerFrontend"),
123-
assembly / assemblyJarName := "onion.jar"
125+
assembly / assemblyJarName := "onion.jar",
126+
assembly / assemblyMergeStrategy := {
127+
case "module-info.class" => MergeStrategy.discard
128+
case x =>
129+
val oldStrategy = (assembly / assemblyMergeStrategy).value
130+
oldStrategy(x)
131+
}
124132
)
125133

126-
fork in run := true
134+
fork in run := true
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
Main-Class: onion.tools.CompilerFrontend
2-
Class-Path: lib/bcel.jar lib/scala-compiler.jar lib/scala-library.jar lib/onion-library.jar
2+
Class-Path: lib/scala-compiler.jar lib/scala-library.jar lib/onion-library.jar

0 commit comments

Comments
 (0)