Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
70eedf6
Add opcodes for type conversions to code-generator.ts
AprupKale Jan 14, 2025
64e245d
Add implicit type conversions in MethodInvocation to code-generator.ts
AprupKale Jan 14, 2025
a33c9af
Add implicit type conversions in MethodInvocation to code-generator.ts
AprupKale Jan 14, 2025
1848b4d
Handle stack size during primitive type conversions in code-generator.ts
AprupKale Jan 14, 2025
f88069e
Handle type conversions in binary expressions in code-generator.ts
AprupKale Jan 21, 2025
db87720
Fix bugs with float conversions
AprupKale Jan 21, 2025
6e0a2d7
Allow primitive types to be safely converted to String
AprupKale Jan 21, 2025
7e58159
Allow primitive types other than boolean in ternary conditional
AprupKale Jan 21, 2025
6bbafe7
Fix bugs in type checker
AprupKale Jan 21, 2025
57eeb8b
Enable unary expressions for non-integer types
AprupKale Jan 21, 2025
2a2cc0b
Fix bug in type conversion for binary expressions
AprupKale Jan 25, 2025
0799bf7
Add type cast support to the compiler
AprupKale Jan 25, 2025
fe76603
Add type cast support to the type checker
AprupKale Jan 26, 2025
345a8c8
Add switch statement support to the AST extractor and the compiler
AprupKale Feb 17, 2025
2038d8b
Add switch statement support to the compiler for integer like types (…
AprupKale Feb 18, 2025
91691ad
Add switch statement support to the compiler for String type
AprupKale Feb 18, 2025
54c0e05
Add overloading support to the compiler
AprupKale Mar 4, 2025
c12fbb8
Handle ambiguity during overloading in the compiler
AprupKale Mar 4, 2025
28a59e1
Modify type checker for overloading support
AprupKale Mar 4, 2025
f0c86ed
Change symbol-table.ts and compiler.ts logic for overriding. Add test…
AprupKale Apr 3, 2025
374c8c1
Add test cases for method overriding.
AprupKale Apr 3, 2025
35bcce8
Fix bugs in symbol-table.ts and compiler.ts logic. Add method invocat…
AprupKale Apr 3, 2025
d4d4bf1
Fix method invocation logic in target loading for qualified calls
AprupKale Apr 3, 2025
1ca1198
Fix bugs in method invocation logic for static method calls, and in s…
AprupKale Apr 6, 2025
0bc9b53
Modify the compiler to return multiple class files with their file na…
AprupKale Apr 6, 2025
d2517b2
Fix bug to not allow final methods to be overriden
AprupKale Apr 6, 2025
68da25d
Merge branch 'main' into method-overloading-overriding
kjw142857 May 20, 2026
805b448
resolve merge conflicts and remove duplication
kjw142857 May 20, 2026
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
60 changes: 60 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Copilot Instructions for java-slang

## What this repo is
- A TypeScript implementation of a Java subset used by Source Academy.
- Two execution models are present: the source-level evaluator in `src/ec-evaluator`, and the JVM bytecode runtime in `src/jvm`.
- The compiler lives in `src/compiler` and emits `ClassFile` objects defined under `src/ClassFile/types`.

## Primary workflows
- Build: `yarn build`
- Test: `yarn test`
- Watch tests: `yarn test:watch`
- Lint: `yarn eslint`
- Format: `yarn format`
- Generate docs: `yarn jsdoc`

## Key entrypoints
- `src/index.ts` exports the public API: `astToString`, `ECE`, `JVM`, `typeCheck`, `compile`, `compileFromSource`.
- `src/compiler/index.ts` is the compiler entrypoint; `compileFromSource` parses Java text with `peggy` and then compiles the AST.
- `src/ec-evaluator/index.ts` is the source-level interpreter entrypoint; use `runECEvaluator(code, targetStep)`.
- `src/jvm/index.ts` is the JVM bootstrap entrypoint; use `setupJVM(...)` and then call the returned `runJVM()`.

## Architecture and boundaries
- `src/ast`: parser and AST utilities for the Java subset.
- `src/compiler`: parser grammar, compiler, and classfile generation.
- `src/ClassFile`: bytecode metadata types for class files.
- `src/jvm`: JVM runtime, class loading, JNI/native integration, threadpool, and unsafe heap.
- `src/ec-evaluator`: an alternative evaluator for source Java semantics, separate from the JVM runtime.
- `src/types`: shared type-checking and semantic utilities used by the package API.

## JVM-specific patterns
- JVM setup is callback-driven. `src/jvm/index.ts` expects callbacks for:
- `readFileSync(path): ClassFile`
- `readFile(path): Promise<any>`
- `stdout(message)` and `stderr(message)`
- optional `onFinish()`
- Native methods are loaded via JNI and may be deferred. See `src/jvm/jni.ts` and `src/jvm/README.md`.
- The JVM uses a bootstrap/application classloader model. `src/jvm/ClassLoader/AbstractClassLoader.ts` defines parent delegation and class loading.
- `src/jvm/utils/CustomSystem.ts` adapts host I/O and module loading into the JVM runtime.

## Project-specific conventions
- All runtime entrypoints are named explicitly and exported from `src/index.ts`.
- The repository expects TypeScript compile output to land in `dist/`; `package.json` uses `tsc --build --force`.
- The codebase uses `yarn` uniformly for install/build/test rather than raw `npm`.
- Tests are located alongside source in `src/**/__tests__`; root-level Jest config is `jest.config.js`.

## Useful file references
- Compiler grammar and parser helpers: `src/compiler/grammar.ts`, `src/compiler/peggy-functions.ts`
- JVM runtime orchestration: `src/jvm/jvm.ts`
- Native/JNI patterns: `src/jvm/jni.ts`, `src/jvm/README.md`
- Class loading and bytecode model: `src/jvm/ClassLoader/AbstractClassLoader.ts`, `src/ClassFile/types`
- Source-level execution: `src/ec-evaluator/index.ts`

## Notes for changes
- Changes to the compiler should preserve the `ClassFile` model and should be cross-checked against both compiler tests and JVM runtime behavior.
- For JVM work, keep the callback contract stable: `readFileSync` returns parsed `ClassFile`, and native load paths are resolved by `nativesPath` / `javaClassPath`.
- Do not assume the interpreter and JVM behavior are identical; `src/ec-evaluator` is deliberately separate from `src/jvm`.

## If you want to extend this guidance
- Add examples of actual repository-specific small refactors or bugfix patterns discovered during work.
- Document any non-obvious `yarn` or submodule workflow if it becomes required for development.
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
"version": "1.0.14",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": ["dist"],
"files": [
"dist"
],
"repository": {
"type": "git",
"url": "git+https://github.com/source-academy/java-slang.git"
Expand Down Expand Up @@ -40,5 +42,6 @@
"java-parser": "^2.0.5",
"lodash": "^4.17.21",
"peggy": "^4.0.2"
}
},
"packageManager": "yarn@1.22.22+sha1.ac34549e6aa8e7ead463a7407e1c7390f61a6610"
}
5 changes: 5 additions & 0 deletions src/ClassFile/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import { ConstantInfo } from './constants'
import { FieldInfo } from './fields'
import { MethodInfo } from './methods'

export interface Class {
classFile: ClassFile
className: string
}

export interface ClassFile {
magic: number
minorVersion: number
Expand Down
139 changes: 139 additions & 0 deletions src/ast/__tests__/expression-extractor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1035,3 +1035,142 @@ describe("extract ClassInstanceCreationExpression correctly", () => {
expect(ast).toEqual(expectedAst);
});
});

describe("extract CastExpression correctly", () => {
it("extract CastExpression int to char correctly", () => {
const programStr = `
class Test {
void test() {
char c = (char) 65;
}
}
`;

const expectedAst: AST = {
kind: "CompilationUnit",
importDeclarations: [],
topLevelClassOrInterfaceDeclarations: [
{
kind: "NormalClassDeclaration",
classModifier: [],
typeIdentifier: "Test",
classBody: [
{
kind: "MethodDeclaration",
methodModifier: [],
methodHeader: {
result: "void",
identifier: "test",
formalParameterList: [],
},
methodBody: {
kind: "Block",
blockStatements: [
{
kind: "LocalVariableDeclarationStatement",
localVariableType: "char",
variableDeclaratorList: [
{
kind: "VariableDeclarator",
variableDeclaratorId: "c",
variableInitializer: {
kind: "CastExpression",
type: "char",
expression: {
kind: "Literal",
literalType: {
kind: "DecimalIntegerLiteral",
value: "65",
},
location: expect.anything(),
},
location: expect.anything(),
},
},
],
location: expect.anything(),
},
],
location: expect.anything(),
},
location: expect.anything(),
},
],
location: expect.anything(),
},
],
location: expect.anything(),
};

const ast = parse(programStr);
expect(ast).toEqual(expectedAst);
});

it("extract CastExpression double to int correctly", () => {
const programStr = `
class Test {
void test() {
int x = (int) 3.14;
}
}
`;

const expectedAst: AST = {
kind: "CompilationUnit",
importDeclarations: [],
topLevelClassOrInterfaceDeclarations: [
{
kind: "NormalClassDeclaration",
classModifier: [],
typeIdentifier: "Test",
classBody: [
{
kind: "MethodDeclaration",
methodModifier: [],
methodHeader: {
result: "void",
identifier: "test",
formalParameterList: [],
},
methodBody: {
kind: "Block",
blockStatements: [
{
kind: "LocalVariableDeclarationStatement",
localVariableType: "int",
variableDeclaratorList: [
{
kind: "VariableDeclarator",
variableDeclaratorId: "x",
variableInitializer: {
kind: "CastExpression",
type: "int",
expression: {
kind: "Literal",
literalType: {
kind: "DecimalFloatingPointLiteral",
value: "3.14",
}
},
location: expect.anything(),
},
},
],
location: expect.anything(),
},
],
location: expect.anything(),
},
location: expect.anything(),
},
],
location: expect.anything(),
},
],
location: expect.anything(),
};

const ast = parse(programStr);
expect(ast).toEqual(expectedAst);
});
});
Loading
Loading