unused_variable_warnings #3
33 changed files with 248 additions and 196 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -33,3 +33,8 @@ c65gm
|
||||||
*.sym
|
*.sym
|
||||||
*.prg
|
*.prg
|
||||||
*.s
|
*.s
|
||||||
|
|
||||||
|
.cache/
|
||||||
|
.env
|
||||||
|
.local/
|
||||||
|
opencode-config/package-lock.json
|
||||||
|
|
|
||||||
167
AGENTS.md
Normal file
167
AGENTS.md
Normal file
|
|
@ -0,0 +1,167 @@
|
||||||
|
# c65gm Agent Instructions
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
c65gm is a high-level 6502 cross-compiler targeting the ACME Cross-Assembler for Commodore 64 and similar 6502-based platforms. It provides a more expressive language for writing 6502 assembly programs with modern programming constructs.
|
||||||
|
|
||||||
|
## Key Documentation Locations
|
||||||
|
|
||||||
|
### Primary Documentation
|
||||||
|
1. **README.md** - Project overview, building, usage, and requirements
|
||||||
|
2. **language.md** - Complete language reference with examples (1091 lines)
|
||||||
|
3. **syntax.md** - Syntax rules and preprocessor directives (646 lines)
|
||||||
|
4. **commands.md** - Complete command reference (776 lines)
|
||||||
|
|
||||||
|
### Code Structure
|
||||||
|
- **main.go** - Entry point and command-line interface
|
||||||
|
- **internal/compiler/** - Core compiler implementation
|
||||||
|
- **internal/preproc/** - Preprocessor implementation
|
||||||
|
- **internal/commands/** - Individual command implementations
|
||||||
|
- **internal/utils/** - Utility functions
|
||||||
|
- **lib/** - Standard library files for C64 development
|
||||||
|
- **examples/** - Example programs demonstrating language features
|
||||||
|
|
||||||
|
### Standard Library (lib/)
|
||||||
|
- **c64start.c65** - Required for C64 executables (BASIC loader setup)
|
||||||
|
- **c64defs.c65** - C64 hardware definitions (colors, addresses, etc.)
|
||||||
|
- **c64kernal.c65** - Kernal routine wrappers
|
||||||
|
- **c64scr.c65** - Screen manipulation functions
|
||||||
|
- **string.c65** - String handling functions
|
||||||
|
- **memlib.c65** - Memory management functions
|
||||||
|
- **fat16/** - FAT16 filesystem support
|
||||||
|
- **koalalib.c65** - Koala graphics support
|
||||||
|
|
||||||
|
## Language Features to Note
|
||||||
|
|
||||||
|
### Key Concepts
|
||||||
|
1. **Type system**: BYTE (8-bit) and WORD (16-bit) variables with scope resolution
|
||||||
|
2. **Functions**: Named functions with parameters and call graph analysis
|
||||||
|
3. **Control flow**: IF/ENDIF, WHILE/WEND, FOR loops, SWITCH/CASE
|
||||||
|
4. **Memory operations**: PEEK/POKE/PEEKW/POKEW with zero-page optimization
|
||||||
|
5. **Preprocessor**: File inclusion, macros, conditional compilation, Starlark scripting
|
||||||
|
6. **Optimizations**: Constant folding, self-assignment detection
|
||||||
|
7. **Safety features**: Compile-time detection of overlapping absolute addresses
|
||||||
|
|
||||||
|
### Important Syntax Rules
|
||||||
|
1. **No operator precedence**: Expressions evaluate strictly left-to-right
|
||||||
|
2. **Memory-mapped variables**: Use `@` to place variables at specific addresses
|
||||||
|
3. **Constants**: Prefer `BYTE CONST`/`WORD CONST` over `#DEFINE`
|
||||||
|
4. **Zero-page optimization**: Place frequently accessed pointers in zero page ($00-$FF)
|
||||||
|
5. **Include guards**: Always use `#IFNDEF` in library files
|
||||||
|
|
||||||
|
### Special Blocks
|
||||||
|
1. **ASM blocks**: Inline assembly code
|
||||||
|
2. **SCRIPT blocks**: Starlark code for compile-time code generation
|
||||||
|
3. **SCRIPT LIBRARY blocks**: Reusable Starlark functions
|
||||||
|
4. **SCRIPT MACRO blocks**: Parameterized macros for inline expansion
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### Program Structure
|
||||||
|
```c65
|
||||||
|
#INCLUDE <c64start.c65>
|
||||||
|
#INCLUDE <c64defs.c65>
|
||||||
|
|
||||||
|
GOTO start // Jump over function definitions
|
||||||
|
|
||||||
|
// Variables and functions here
|
||||||
|
|
||||||
|
LABEL start // Program entry point
|
||||||
|
main()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Library Structure
|
||||||
|
```c65
|
||||||
|
#IFNDEF __MY_LIBRARY
|
||||||
|
#DEFINE __MY_LIBRARY = 1
|
||||||
|
|
||||||
|
GOTO lib_mylib_skip
|
||||||
|
|
||||||
|
// Library code here
|
||||||
|
|
||||||
|
LABEL lib_mylib_skip
|
||||||
|
#IFEND
|
||||||
|
```
|
||||||
|
|
||||||
|
### Memory Operations
|
||||||
|
- Use `PEEK`/`POKE` for byte access
|
||||||
|
- Use `PEEKW`/`POKEW` for word (16-bit) access
|
||||||
|
- For indexed access, address must be a WORD variable in zero page
|
||||||
|
|
||||||
|
## Development Guidelines
|
||||||
|
|
||||||
|
### Environment Constraints
|
||||||
|
**IMPORTANT**: The agent runs in a Docker container without access to compilers, testing tools, or external build systems. All compilation and testing must be performed by the user. The agent can only:
|
||||||
|
1. Read and analyze source code
|
||||||
|
2. Make code changes
|
||||||
|
3. Provide instructions for the user to compile and test
|
||||||
|
|
||||||
|
### File Access Restrictions
|
||||||
|
**CRITICAL**: The agent must only access normal project files within the current working directory. The agent must NEVER:
|
||||||
|
1. Look at files outside the project directory (e.g., `/tmp/`, `/etc/`, `/home/`, etc.)
|
||||||
|
2. Read or attempt to access system files, environment files (`.env`), or configuration files outside the project
|
||||||
|
3. Search for or read files containing secrets, credentials, or sensitive information
|
||||||
|
4. Attempt to access files in parent directories or unrelated paths
|
||||||
|
|
||||||
|
All file operations must be restricted to the project's source code and documentation files only.
|
||||||
|
|
||||||
|
### When Modifying the Compiler
|
||||||
|
1. Check `internal/commands/` for command implementations
|
||||||
|
2. Check `internal/compiler/` for core compiler logic
|
||||||
|
3. Check `internal/preproc/` for preprocessor functionality
|
||||||
|
4. **DO NOT run tests** - provide instructions for the user to run tests
|
||||||
|
|
||||||
|
### When Adding New Features
|
||||||
|
1. Follow existing patterns in command implementations
|
||||||
|
2. Add comprehensive tests
|
||||||
|
3. Update documentation in appropriate .md files
|
||||||
|
4. Consider adding examples in `examples/` directory
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
**IMPORTANT**: The agent cannot run tests. Provide these instructions to the user:
|
||||||
|
- Run all tests: `go test ./...`
|
||||||
|
- Run specific package tests: `go test ./internal/compiler`
|
||||||
|
- Test with verbose output: `go test -v ./...`
|
||||||
|
|
||||||
|
## Common Pitfalls
|
||||||
|
|
||||||
|
1. **Expression evaluation**: Remember no operator precedence
|
||||||
|
2. **Zero-page requirements**: Indexed memory operations require zero-page addresses
|
||||||
|
3. **Include guards**: Essential for library files to prevent multiple inclusion
|
||||||
|
4. **Program structure**: Always use `GOTO start` to jump over function definitions
|
||||||
|
5. **String handling**: Strings are passed as pointers to WORD parameters
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
### Compilation
|
||||||
|
**IMPORTANT**: The agent cannot compile code. Provide these instructions to the user:
|
||||||
|
```bash
|
||||||
|
./c65gm -in input.c65 -out output.asm
|
||||||
|
acme -f cbm -o output.prg output.asm
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
- `C65LIBPATH`: Library search path for `#INCLUDE <file>`
|
||||||
|
|
||||||
|
### Editor Support
|
||||||
|
- Kate syntax: `editor_syntaxes/kate/`
|
||||||
|
- Sublime syntax: `editor_syntaxes/sublime/`
|
||||||
|
|
||||||
|
## Where to Look for Specifics
|
||||||
|
|
||||||
|
### Language Syntax
|
||||||
|
- `language.md`: Sections 1-10 cover all language features
|
||||||
|
- `syntax.md`: Detailed syntax rules and preprocessor directives
|
||||||
|
- `commands.md`: Complete command reference with examples
|
||||||
|
|
||||||
|
### Implementation Details
|
||||||
|
- `internal/compiler/compiler.go`: Main compiler logic
|
||||||
|
- `internal/commands/*.go`: Individual command implementations
|
||||||
|
- `internal/preproc/preproc.go`: Preprocessor implementation
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
- `examples/`: Working example programs
|
||||||
|
- `lib/`: Standard library usage examples
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
- `*_test.go` files throughout the codebase
|
||||||
|
- `examples/`: Functional test programs
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
FROM node:18-alpine
|
|
||||||
WORKDIR /app
|
|
||||||
RUN apk add --no-cache bash
|
|
||||||
ENV SHELL=/bin/bash
|
|
||||||
RUN npm install -g @anthropic-ai/claude-code
|
|
||||||
CMD ["claude"]
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
export DOCKER_UID=$(id -u)
|
|
||||||
export DOCKER_GID=$(id -g)
|
|
||||||
docker compose run --rm claude-c65gm
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
services:
|
services:
|
||||||
claude-c65gm:
|
opencode-deepseek-c65gm:
|
||||||
build: .
|
#image: ghcr.io/anomalyco/opencode:0.0.0-beta-202604081541
|
||||||
|
image: ghcr.io/anomalyco/opencode:latest
|
||||||
user: "${DOCKER_UID}:${DOCKER_GID}"
|
user: "${DOCKER_UID}:${DOCKER_GID}"
|
||||||
|
working_dir: /app
|
||||||
volumes:
|
volumes:
|
||||||
- .:/app
|
- .:/app
|
||||||
|
- ./opencode-config:/app/.config/opencode
|
||||||
|
- ./opencode-data:/home/opencode/.local/share/opencode
|
||||||
environment:
|
environment:
|
||||||
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
|
- DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY}
|
||||||
- CLAUDE_CONFIG_DIR=/app/.claude
|
|
||||||
- HOME=/app
|
- HOME=/app
|
||||||
- DISABLE_AUTOUPDATER=1
|
|
||||||
stdin_open: true
|
stdin_open: true
|
||||||
tty: true
|
tty: true
|
||||||
|
|
|
||||||
|
|
@ -68,13 +68,7 @@ func (c *AddCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext)
|
||||||
scope := ctx.CurrentScope()
|
scope := ctx.CurrentScope()
|
||||||
|
|
||||||
// Create constant lookup function
|
// Create constant lookup function
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine syntax and parse accordingly
|
// Determine syntax and parse accordingly
|
||||||
if strings.ToUpper(params[0]) == "ADD" {
|
if strings.ToUpper(params[0]) == "ADD" {
|
||||||
|
|
|
||||||
|
|
@ -68,13 +68,7 @@ func (c *AndCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext)
|
||||||
scope := ctx.CurrentScope()
|
scope := ctx.CurrentScope()
|
||||||
|
|
||||||
// Create constant lookup function
|
// Create constant lookup function
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine syntax and parse accordingly
|
// Determine syntax and parse accordingly
|
||||||
if strings.ToUpper(params[0]) == "AND" {
|
if strings.ToUpper(params[0]) == "AND" {
|
||||||
|
|
|
||||||
|
|
@ -55,13 +55,7 @@ func (c *ByteCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext
|
||||||
scope := ctx.FunctionHandler.CurrentFunction()
|
scope := ctx.FunctionHandler.CurrentFunction()
|
||||||
|
|
||||||
// Create constant lookup function
|
// Create constant lookup function
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(ctx.CurrentScope())
|
||||||
sym := ctx.SymbolTable.Lookup(name, ctx.CurrentScope())
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
switch paramCount {
|
switch paramCount {
|
||||||
case 2:
|
case 2:
|
||||||
|
|
|
||||||
|
|
@ -39,13 +39,7 @@ func (c *CaseCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext
|
||||||
}
|
}
|
||||||
|
|
||||||
scope := ctx.CurrentScope()
|
scope := ctx.CurrentScope()
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the case value
|
// Parse the case value
|
||||||
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
||||||
|
|
|
||||||
|
|
@ -97,13 +97,7 @@ func (c *DecrCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext
|
||||||
}
|
}
|
||||||
|
|
||||||
// Old syntax allows absolute addresses
|
// Old syntax allows absolute addresses
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
s := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if s != nil && s.IsConst() {
|
|
||||||
return int64(s.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
val, evalErr := utils.EvaluateExpression(targetParam, constLookup)
|
val, evalErr := utils.EvaluateExpression(targetParam, constLookup)
|
||||||
if evalErr != nil {
|
if evalErr != nil {
|
||||||
|
|
|
||||||
|
|
@ -48,13 +48,7 @@ func (c *ForCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
scope := ctx.CurrentScope()
|
scope := ctx.CurrentScope()
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse variable
|
// Parse variable
|
||||||
varName := params[1]
|
varName := params[1]
|
||||||
|
|
|
||||||
|
|
@ -70,13 +70,7 @@ func (c *GosubCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContex
|
||||||
|
|
||||||
scope := ctx.CurrentScope()
|
scope := ctx.CurrentScope()
|
||||||
|
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse target (param 2)
|
// Parse target (param 2)
|
||||||
targetParam := params[1]
|
targetParam := params[1]
|
||||||
|
|
|
||||||
|
|
@ -52,13 +52,7 @@ func (c *GotoCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext
|
||||||
targetParam := params[1]
|
targetParam := params[1]
|
||||||
scope := ctx.CurrentScope()
|
scope := ctx.CurrentScope()
|
||||||
|
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try ParseOperandParam - handles variables, constants, expressions
|
// Try ParseOperandParam - handles variables, constants, expressions
|
||||||
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
||||||
|
|
|
||||||
|
|
@ -40,13 +40,7 @@ func (c *IfCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
scope := ctx.CurrentScope()
|
scope := ctx.CurrentScope()
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse param1
|
// Parse param1
|
||||||
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
||||||
|
|
|
||||||
|
|
@ -97,13 +97,7 @@ func (c *IncrCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext
|
||||||
}
|
}
|
||||||
|
|
||||||
// Old syntax allows absolute addresses
|
// Old syntax allows absolute addresses
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
s := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if s != nil && s.IsConst() {
|
|
||||||
return int64(s.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
val, evalErr := utils.EvaluateExpression(targetParam, constLookup)
|
val, evalErr := utils.EvaluateExpression(targetParam, constLookup)
|
||||||
if evalErr != nil {
|
if evalErr != nil {
|
||||||
|
|
|
||||||
|
|
@ -62,13 +62,7 @@ func (c *LetCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext)
|
||||||
scope := ctx.CurrentScope()
|
scope := ctx.CurrentScope()
|
||||||
|
|
||||||
// Create constant lookup function
|
// Create constant lookup function
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine syntax and parse accordingly
|
// Determine syntax and parse accordingly
|
||||||
if strings.ToUpper(params[0]) == "LET" {
|
if strings.ToUpper(params[0]) == "LET" {
|
||||||
|
|
|
||||||
|
|
@ -68,13 +68,7 @@ func (c *OrCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext)
|
||||||
scope := ctx.CurrentScope()
|
scope := ctx.CurrentScope()
|
||||||
|
|
||||||
// Create constant lookup function
|
// Create constant lookup function
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine syntax and parse accordingly
|
// Determine syntax and parse accordingly
|
||||||
if strings.ToUpper(params[0]) == "OR" {
|
if strings.ToUpper(params[0]) == "OR" {
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,7 @@ func (c *OriginCommand) Interpret(line preproc.Line, ctx *compiler.CompilerConte
|
||||||
}
|
}
|
||||||
|
|
||||||
scope := ctx.CurrentScope()
|
scope := ctx.CurrentScope()
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
val, err := utils.EvaluateExpression(params[1], constLookup)
|
val, err := utils.EvaluateExpression(params[1], constLookup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -115,13 +115,7 @@ func (c *PeekCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext
|
||||||
// Parse address - may have [offset]
|
// Parse address - may have [offset]
|
||||||
baseAddr, offsetParam := parseOffset(addrParam)
|
baseAddr, offsetParam := parseOffset(addrParam)
|
||||||
|
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to parse base address
|
// Try to parse base address
|
||||||
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
||||||
|
|
|
||||||
|
|
@ -116,13 +116,7 @@ func (c *PeekWCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContex
|
||||||
// Parse address - may have [offset]
|
// Parse address - may have [offset]
|
||||||
baseAddr, offsetParam := parseOffsetW(addrParam)
|
baseAddr, offsetParam := parseOffsetW(addrParam)
|
||||||
|
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to parse base address
|
// Try to parse base address
|
||||||
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
||||||
|
|
|
||||||
|
|
@ -74,13 +74,7 @@ func (c *PointerCommand) Interpret(line preproc.Line, ctx *compiler.CompilerCont
|
||||||
// Parse target (param 4)
|
// Parse target (param 4)
|
||||||
targetParam := params[3]
|
targetParam := params[3]
|
||||||
|
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try ParseOperandParam - handles variables, constants, expressions
|
// Try ParseOperandParam - handles variables, constants, expressions
|
||||||
varName, _, value, isVar, err := compiler.ParseOperandParam(
|
varName, _, value, isVar, err := compiler.ParseOperandParam(
|
||||||
|
|
|
||||||
|
|
@ -83,13 +83,7 @@ func (c *PokeCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext
|
||||||
addrParam := params[1]
|
addrParam := params[1]
|
||||||
baseAddr, offsetParam := parsePOKEOffset(addrParam)
|
baseAddr, offsetParam := parsePOKEOffset(addrParam)
|
||||||
|
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to parse base address
|
// Try to parse base address
|
||||||
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
||||||
|
|
|
||||||
|
|
@ -82,13 +82,7 @@ func (c *PokeWCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContex
|
||||||
addrParam := params[1]
|
addrParam := params[1]
|
||||||
baseAddr, offsetParam := parsePOKEWOffset(addrParam)
|
baseAddr, offsetParam := parsePOKEWOffset(addrParam)
|
||||||
|
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to parse base address
|
// Try to parse base address
|
||||||
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
||||||
|
|
|
||||||
|
|
@ -71,13 +71,7 @@ func (c *SubtractCommand) Interpret(line preproc.Line, ctx *compiler.CompilerCon
|
||||||
scope := ctx.CurrentScope()
|
scope := ctx.CurrentScope()
|
||||||
|
|
||||||
// Create constant lookup function
|
// Create constant lookup function
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine syntax and parse accordingly
|
// Determine syntax and parse accordingly
|
||||||
kw := strings.ToUpper(params[0])
|
kw := strings.ToUpper(params[0])
|
||||||
|
|
|
||||||
|
|
@ -33,13 +33,7 @@ func (c *SwitchCommand) Interpret(line preproc.Line, ctx *compiler.CompilerConte
|
||||||
}
|
}
|
||||||
|
|
||||||
scope := ctx.CurrentScope()
|
scope := ctx.CurrentScope()
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the switch variable/expression
|
// Parse the switch variable/expression
|
||||||
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,7 @@ func (c *WhileCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContex
|
||||||
}
|
}
|
||||||
|
|
||||||
scope := ctx.CurrentScope()
|
scope := ctx.CurrentScope()
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse param1
|
// Parse param1
|
||||||
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
||||||
|
|
|
||||||
|
|
@ -57,13 +57,7 @@ func (c *WordCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext
|
||||||
scope := ctx.FunctionHandler.CurrentFunction()
|
scope := ctx.FunctionHandler.CurrentFunction()
|
||||||
|
|
||||||
// Create constant lookup function
|
// Create constant lookup function
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(ctx.CurrentScope())
|
||||||
sym := ctx.SymbolTable.Lookup(name, ctx.CurrentScope())
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
switch paramCount {
|
switch paramCount {
|
||||||
case 2:
|
case 2:
|
||||||
|
|
|
||||||
|
|
@ -68,13 +68,7 @@ func (c *XorCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext)
|
||||||
scope := ctx.CurrentScope()
|
scope := ctx.CurrentScope()
|
||||||
|
|
||||||
// Create constant lookup function
|
// Create constant lookup function
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine syntax and parse accordingly
|
// Determine syntax and parse accordingly
|
||||||
if strings.ToUpper(params[0]) == "XOR" {
|
if strings.ToUpper(params[0]) == "XOR" {
|
||||||
|
|
|
||||||
|
|
@ -343,12 +343,7 @@ func (fh *FunctionHandler) HandleFuncCall(line preproc.Line) ([]string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use ParseOperandParam for variables, constants, and expressions
|
// Use ParseOperandParam for variables, constants, and expressions
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := fh.symTable.ConstantLookupFunc(fh.currentFuncs)
|
||||||
if sym := fh.symTable.Lookup(name, fh.currentFuncs); sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
_, _, value, isVar, err := ParseOperandParam(
|
_, _, value, isVar, err := ParseOperandParam(
|
||||||
arg, fh.symTable, fh.currentFuncs, constLookup)
|
arg, fh.symTable, fh.currentFuncs, constLookup)
|
||||||
|
|
@ -632,13 +627,7 @@ func (fh *FunctionHandler) parseImplicitDecl(decl string, funcName string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create constant lookup function for address evaluation
|
// Create constant lookup function for address evaluation
|
||||||
constLookup := func(name string) (int64, bool) {
|
constLookup := fh.symTable.ConstantLookupFunc([]string{funcName})
|
||||||
sym := fh.symTable.Lookup(name, []string{funcName})
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse address (supports $hex and decimal) using EvaluateExpression
|
// Parse address (supports $hex and decimal) using EvaluateExpression
|
||||||
addr, err := utils.EvaluateExpression(addrStr, constLookup)
|
addr, err := utils.EvaluateExpression(addrStr, constLookup)
|
||||||
|
|
|
||||||
|
|
@ -177,13 +177,7 @@ func evaluateMacroArg(arg string, ctx *CompilerContext) (starlark.Value, error)
|
||||||
arg = strings.TrimSpace(arg)
|
arg = strings.TrimSpace(arg)
|
||||||
|
|
||||||
// Create lookup function for constants
|
// Create lookup function for constants
|
||||||
lookup := func(name string) (int64, bool) {
|
lookup := ctx.SymbolTable.ConstantLookupFunc(nil)
|
||||||
sym := ctx.SymbolTable.Lookup(name, nil)
|
|
||||||
if sym != nil && sym.IsConst() {
|
|
||||||
return int64(sym.Value), true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to evaluate as expression (number, constant, arithmetic)
|
// Try to evaluate as expression (number, constant, arithmetic)
|
||||||
val, err := utils.EvaluateExpression(arg, lookup)
|
val, err := utils.EvaluateExpression(arg, lookup)
|
||||||
|
|
|
||||||
|
|
@ -253,6 +253,24 @@ func (st *SymbolTable) ExpandName(name string, currentScopes []string) string {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LookupConstant looks up a constant by name and returns its value if found
|
||||||
|
// Returns (value, true) if symbol exists and is a constant, (0, false) otherwise
|
||||||
|
func (st *SymbolTable) LookupConstant(name string, currentScopes []string) (int64, bool) {
|
||||||
|
sym := st.Lookup(name, currentScopes)
|
||||||
|
if sym != nil && sym.IsConst() {
|
||||||
|
return int64(sym.Value), true
|
||||||
|
}
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConstantLookupFunc returns a ConstantLookup function that captures the current scopes
|
||||||
|
// This can be used directly with utils.EvaluateExpression
|
||||||
|
func (st *SymbolTable) ConstantLookupFunc(currentScopes []string) func(string) (int64, bool) {
|
||||||
|
return func(name string) (int64, bool) {
|
||||||
|
return st.LookupConstant(name, currentScopes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// String representation for debugging
|
// String representation for debugging
|
||||||
func (s *Symbol) String() string {
|
func (s *Symbol) String() string {
|
||||||
var parts []string
|
var parts []string
|
||||||
|
|
|
||||||
13
opencode-config/opencode.json
Normal file
13
opencode-config/opencode.json
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://opencode.ai/config.json",
|
||||||
|
"agent": {
|
||||||
|
"plan": {
|
||||||
|
"model": "deepseek/deepseek-reasoner",
|
||||||
|
"description": "Planning and architecture analysis using DeepSeek Reasoner"
|
||||||
|
},
|
||||||
|
"build": {
|
||||||
|
"model": "deepseek/deepseek-chat",
|
||||||
|
"description": "Implementation and coding using DeepSeek Chat"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
opencode-docker.sh
Normal file
12
opencode-docker.sh
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
export DOCKER_UID=$(id -u)
|
||||||
|
export DOCKER_GID=$(id -g)
|
||||||
|
|
||||||
|
# Load from .env if it exists
|
||||||
|
if [ -f .env ]; then
|
||||||
|
export $(grep -v '^#' .env | xargs)
|
||||||
|
fi
|
||||||
|
|
||||||
|
docker compose run --rm opencode-deepseek-c65gm
|
||||||
Loading…
Reference in a new issue