First commit refactoring and centralizing constant handling all over
This commit is contained in:
parent
4f4df41c18
commit
b25c11ae64
33 changed files with 248 additions and 196 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -33,3 +33,8 @@ c65gm
|
|||
*.sym
|
||||
*.prg
|
||||
*.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:
|
||||
claude-c65gm:
|
||||
build: .
|
||||
opencode-deepseek-c65gm:
|
||||
#image: ghcr.io/anomalyco/opencode:0.0.0-beta-202604081541
|
||||
image: ghcr.io/anomalyco/opencode:latest
|
||||
user: "${DOCKER_UID}:${DOCKER_GID}"
|
||||
working_dir: /app
|
||||
volumes:
|
||||
- .:/app
|
||||
- ./opencode-config:/app/.config/opencode
|
||||
- ./opencode-data:/home/opencode/.local/share/opencode
|
||||
environment:
|
||||
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
|
||||
- CLAUDE_CONFIG_DIR=/app/.claude
|
||||
- DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY}
|
||||
- HOME=/app
|
||||
- DISABLE_AUTOUPDATER=1
|
||||
stdin_open: true
|
||||
tty: true
|
||||
|
|
|
|||
|
|
@ -68,13 +68,7 @@ func (c *AddCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext)
|
|||
scope := ctx.CurrentScope()
|
||||
|
||||
// Create constant lookup function
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Determine syntax and parse accordingly
|
||||
if strings.ToUpper(params[0]) == "ADD" {
|
||||
|
|
|
|||
|
|
@ -68,13 +68,7 @@ func (c *AndCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext)
|
|||
scope := ctx.CurrentScope()
|
||||
|
||||
// Create constant lookup function
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Determine syntax and parse accordingly
|
||||
if strings.ToUpper(params[0]) == "AND" {
|
||||
|
|
|
|||
|
|
@ -55,13 +55,7 @@ func (c *ByteCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext
|
|||
scope := ctx.FunctionHandler.CurrentFunction()
|
||||
|
||||
// Create constant lookup function
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, ctx.CurrentScope())
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(ctx.CurrentScope())
|
||||
|
||||
switch paramCount {
|
||||
case 2:
|
||||
|
|
|
|||
|
|
@ -39,13 +39,7 @@ func (c *CaseCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext
|
|||
}
|
||||
|
||||
scope := ctx.CurrentScope()
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Parse the case value
|
||||
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
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
s := ctx.SymbolTable.Lookup(name, scope)
|
||||
if s != nil && s.IsConst() {
|
||||
return int64(s.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
val, evalErr := utils.EvaluateExpression(targetParam, constLookup)
|
||||
if evalErr != nil {
|
||||
|
|
|
|||
|
|
@ -48,13 +48,7 @@ func (c *ForCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext)
|
|||
}
|
||||
|
||||
scope := ctx.CurrentScope()
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Parse variable
|
||||
varName := params[1]
|
||||
|
|
|
|||
|
|
@ -70,13 +70,7 @@ func (c *GosubCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContex
|
|||
|
||||
scope := ctx.CurrentScope()
|
||||
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Parse target (param 2)
|
||||
targetParam := params[1]
|
||||
|
|
|
|||
|
|
@ -52,13 +52,7 @@ func (c *GotoCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext
|
|||
targetParam := params[1]
|
||||
scope := ctx.CurrentScope()
|
||||
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Try ParseOperandParam - handles variables, constants, expressions
|
||||
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
||||
|
|
|
|||
|
|
@ -40,13 +40,7 @@ func (c *IfCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext)
|
|||
}
|
||||
|
||||
scope := ctx.CurrentScope()
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Parse param1
|
||||
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
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
s := ctx.SymbolTable.Lookup(name, scope)
|
||||
if s != nil && s.IsConst() {
|
||||
return int64(s.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
val, evalErr := utils.EvaluateExpression(targetParam, constLookup)
|
||||
if evalErr != nil {
|
||||
|
|
|
|||
|
|
@ -62,13 +62,7 @@ func (c *LetCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext)
|
|||
scope := ctx.CurrentScope()
|
||||
|
||||
// Create constant lookup function
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Determine syntax and parse accordingly
|
||||
if strings.ToUpper(params[0]) == "LET" {
|
||||
|
|
|
|||
|
|
@ -68,13 +68,7 @@ func (c *OrCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext)
|
|||
scope := ctx.CurrentScope()
|
||||
|
||||
// Create constant lookup function
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Determine syntax and parse accordingly
|
||||
if strings.ToUpper(params[0]) == "OR" {
|
||||
|
|
|
|||
|
|
@ -36,13 +36,7 @@ func (c *OriginCommand) Interpret(line preproc.Line, ctx *compiler.CompilerConte
|
|||
}
|
||||
|
||||
scope := ctx.CurrentScope()
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
val, err := utils.EvaluateExpression(params[1], constLookup)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -115,13 +115,7 @@ func (c *PeekCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext
|
|||
// Parse address - may have [offset]
|
||||
baseAddr, offsetParam := parseOffset(addrParam)
|
||||
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Try to parse base address
|
||||
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]
|
||||
baseAddr, offsetParam := parseOffsetW(addrParam)
|
||||
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Try to parse base address
|
||||
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)
|
||||
targetParam := params[3]
|
||||
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Try ParseOperandParam - handles variables, constants, expressions
|
||||
varName, _, value, isVar, err := compiler.ParseOperandParam(
|
||||
|
|
|
|||
|
|
@ -83,13 +83,7 @@ func (c *PokeCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext
|
|||
addrParam := params[1]
|
||||
baseAddr, offsetParam := parsePOKEOffset(addrParam)
|
||||
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Try to parse base address
|
||||
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
||||
|
|
|
|||
|
|
@ -82,13 +82,7 @@ func (c *PokeWCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContex
|
|||
addrParam := params[1]
|
||||
baseAddr, offsetParam := parsePOKEWOffset(addrParam)
|
||||
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Try to parse base address
|
||||
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
||||
|
|
|
|||
|
|
@ -71,13 +71,7 @@ func (c *SubtractCommand) Interpret(line preproc.Line, ctx *compiler.CompilerCon
|
|||
scope := ctx.CurrentScope()
|
||||
|
||||
// Create constant lookup function
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Determine syntax and parse accordingly
|
||||
kw := strings.ToUpper(params[0])
|
||||
|
|
|
|||
|
|
@ -33,13 +33,7 @@ func (c *SwitchCommand) Interpret(line preproc.Line, ctx *compiler.CompilerConte
|
|||
}
|
||||
|
||||
scope := ctx.CurrentScope()
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Parse the switch variable/expression
|
||||
varName, varKind, value, isVar, err := compiler.ParseOperandParam(
|
||||
|
|
|
|||
|
|
@ -41,13 +41,7 @@ func (c *WhileCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContex
|
|||
}
|
||||
|
||||
scope := ctx.CurrentScope()
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Parse param1
|
||||
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()
|
||||
|
||||
// Create constant lookup function
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, ctx.CurrentScope())
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(ctx.CurrentScope())
|
||||
|
||||
switch paramCount {
|
||||
case 2:
|
||||
|
|
|
|||
|
|
@ -68,13 +68,7 @@ func (c *XorCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContext)
|
|||
scope := ctx.CurrentScope()
|
||||
|
||||
// Create constant lookup function
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, scope)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := ctx.SymbolTable.ConstantLookupFunc(scope)
|
||||
|
||||
// Determine syntax and parse accordingly
|
||||
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
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
if sym := fh.symTable.Lookup(name, fh.currentFuncs); sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := fh.symTable.ConstantLookupFunc(fh.currentFuncs)
|
||||
|
||||
_, _, value, isVar, err := ParseOperandParam(
|
||||
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
|
||||
constLookup := func(name string) (int64, bool) {
|
||||
sym := fh.symTable.Lookup(name, []string{funcName})
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
constLookup := fh.symTable.ConstantLookupFunc([]string{funcName})
|
||||
|
||||
// Parse address (supports $hex and decimal) using EvaluateExpression
|
||||
addr, err := utils.EvaluateExpression(addrStr, constLookup)
|
||||
|
|
|
|||
|
|
@ -177,13 +177,7 @@ func evaluateMacroArg(arg string, ctx *CompilerContext) (starlark.Value, error)
|
|||
arg = strings.TrimSpace(arg)
|
||||
|
||||
// Create lookup function for constants
|
||||
lookup := func(name string) (int64, bool) {
|
||||
sym := ctx.SymbolTable.Lookup(name, nil)
|
||||
if sym != nil && sym.IsConst() {
|
||||
return int64(sym.Value), true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
lookup := ctx.SymbolTable.ConstantLookupFunc(nil)
|
||||
|
||||
// Try to evaluate as expression (number, constant, arithmetic)
|
||||
val, err := utils.EvaluateExpression(arg, lookup)
|
||||
|
|
|
|||
|
|
@ -253,6 +253,24 @@ func (st *SymbolTable) ExpandName(name string, currentScopes []string) string {
|
|||
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
|
||||
func (s *Symbol) String() 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