Skip to content

Commit

Permalink
extend ast node type to support copy function (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
cornelk authored Nov 9, 2024
1 parent be92a30 commit 53a1a87
Show file tree
Hide file tree
Showing 28 changed files with 380 additions and 60 deletions.
4 changes: 2 additions & 2 deletions assembler/address_assigning_step.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func assignAddressesStep(asm *Assembler) error {
case scopeChange:
aa.currentScope = n.scope

case *scope.Symbol:
case *symbol:
err = assignSymbolAddress(aa, n)

case *variable:
Expand Down Expand Up @@ -104,7 +104,7 @@ func assignBaseAddress(b ast.Base) (uint64, error) {
return uint64(i), nil
}

func assignSymbolAddress(aa addressAssign, sym *scope.Symbol) error {
func assignSymbolAddress(aa addressAssign, sym *symbol) error {
sym.SetAddress(aa.programCounter)
exp := sym.Expression()
if exp != nil && exp.IsEvaluatedAtAddressAssign() {
Expand Down
14 changes: 7 additions & 7 deletions assembler/expression_evaluation_step.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ func evaluateExpressionsStep(asm *Assembler) error {
},
}

for _, seg := range asm.segmentsOrder {
nodes := make([]any, 0, len(seg.nodes))
for segNr, seg := range asm.segmentsOrder {
nodes := make([]ast.Node, 0, len(seg.nodes))

for _, node := range seg.nodes {
for nodeNr, node := range seg.nodes {
remove, err := evaluateNode(&expEval, node)
if err != nil {
return err
return fmt.Errorf("evaluating node %d in segment %d: %w", nodeNr, segNr, err)
}
if !remove {
nodes = append(nodes, node)
Expand Down Expand Up @@ -115,7 +115,7 @@ func evaluateNode(expEval *expressionEvaluation, node any) (bool, error) {
case *data:
return false, parseDataExpression(expEval, n)

case *scope.Symbol:
case *symbol:
return false, parseSymbolExpression(expEval, n)
}

Expand Down Expand Up @@ -162,7 +162,7 @@ func parseDataExpression(expEval *expressionEvaluation, dat *data) error {
}
}

func parseSymbolExpression(expEval *expressionEvaluation, sym *scope.Symbol) error {
func parseSymbolExpression(expEval *expressionEvaluation, sym *symbol) error {
exp := sym.Expression()
if exp == nil || exp.IsEvaluatedAtAddressAssign() {
return nil
Expand All @@ -177,7 +177,7 @@ func parseSymbolExpression(expEval *expressionEvaluation, sym *scope.Symbol) err
}

if sym.Type() == scope.AliasType {
if err := expEval.currentScope.AddSymbol(sym); err != nil {
if err := expEval.currentScope.AddSymbol(sym.Symbol); err != nil {
return fmt.Errorf("setting symbol in scope: %w", err)
}
}
Expand Down
81 changes: 81 additions & 0 deletions assembler/nodes.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package assembler

import (
"maps"
"slices"

"github.com/retroenv/retroasm/expression"
"github.com/retroenv/retroasm/lexer/token"
"github.com/retroenv/retroasm/parser/ast"
Expand Down Expand Up @@ -43,6 +46,21 @@ type data struct {
values []any
}

// Copy returns a copy of the data node.
func (d *data) Copy() ast.Node {
return &data{
address: d.address,
width: d.width,
fill: d.fill,
size: d.size.Copy(),
expression: d.expression.Copy(),
values: slices.Clone(d.values),
}
}

func (d *data) SetComment(_ string) {
}

// instruction of the used architecture.
type instruction struct {
address uint64 // assigned start address of the instruction
Expand All @@ -54,18 +72,81 @@ type instruction struct {
argument any
}

// Copy returns a copy of the instruction node.
func (i *instruction) Copy() ast.Node {
return &instruction{
address: i.address,
size: i.size,
opcodes: i.opcodes,
name: i.name,
addressing: i.addressing,
argument: i.argument,
}
}

func (i *instruction) SetComment(_ string) {
}

type variable struct {
address uint64 // assigned start address of the instruction

v ast.Variable
}

// Copy returns a copy of the variable node.
func (v *variable) Copy() ast.Node {
return &variable{
address: v.address,
v: v.v.Copy().(ast.Variable),
}
}

func (v *variable) SetComment(_ string) {
}

type scopeChange struct {
scope *scope.Scope
}

// Copy returns a copy of the scope change node.
func (s scopeChange) Copy() ast.Node {
return scopeChange{
scope: s.scope,
}
}

func (s scopeChange) SetComment(_ string) {
}

type macro struct {
name string
arguments map[string]int // maps name to position
tokens []token.Token
}

// Copy returns a copy of the macro node.
func (m macro) Copy() ast.Node {
return macro{
name: m.name,
arguments: maps.Clone(m.arguments),
tokens: slices.Clone(m.tokens),
}
}

func (m macro) SetComment(_ string) {
}

// wrap symbol to implement ast.Node interface and avoid cyclic import.
type symbol struct {
*scope.Symbol
}

// Copy returns a copy of the symbol node.
func (s *symbol) Copy() ast.Node {
return &symbol{
Symbol: s.Symbol,
}
}

func (s *symbol) SetComment(_ string) {
}
57 changes: 21 additions & 36 deletions assembler/parse_ast_nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,10 @@ func parseASTNodesStep(asm *Assembler) error {
}

// nolint: cyclop, funlen
func parseASTNode(asm *parseAST, node ast.Node) ([]any, error) {
func parseASTNode(asm *parseAST, node ast.Node) ([]ast.Node, error) {
var (
err error
nodes []any
nodes []ast.Node
)

switch n := node.(type) {
Expand Down Expand Up @@ -110,23 +110,8 @@ func parseASTNode(asm *parseAST, node ast.Node) ([]any, error) {
parseVariable(n)

// default case for node types that do not have special handling at this point
case ast.Configuration,
ast.If,
ast.Ifdef,
ast.Ifndef,
ast.Else,
ast.ElseIf,
ast.Endif,
ast.Identifier,
ast.Error,
ast.Base,
ast.Enum,
ast.EnumEnd:

return []any{n}, nil

default:
return nil, fmt.Errorf("unsupported node type %T", n)
return []ast.Node{n}, nil
}

if err != nil {
Expand Down Expand Up @@ -162,7 +147,7 @@ func parseSegment(asm *parseAST, astSegment ast.Segment) error {

var errNoCurrentSegment = errors.New("no current segment found")

func parseData(astData ast.Data) ([]any, error) {
func parseData(astData ast.Data) ([]ast.Node, error) {
dat := &data{
fill: astData.Fill,
width: astData.Width,
Expand Down Expand Up @@ -195,7 +180,7 @@ func parseData(astData ast.Data) ([]any, error) {
return nil, fmt.Errorf("unsupported data type %d", astData.Type)
}

return []any{dat}, nil
return []ast.Node{dat}, nil
}

func parseDataAddress(dat *data, expression *expression.Expression, refType referenceType) error {
Expand Down Expand Up @@ -236,7 +221,7 @@ func parseDataAddress(dat *data, expression *expression.Expression, refType refe
return nil
}

func parseAlias(asm *parseAST, alias ast.Alias) ([]any, error) {
func parseAlias(asm *parseAST, alias ast.Alias) ([]ast.Node, error) {
typ := scope.AliasType
if !alias.SymbolReusable {
typ = scope.EquType
Expand All @@ -247,19 +232,19 @@ func parseAlias(asm *parseAST, alias ast.Alias) ([]any, error) {
return nil, fmt.Errorf("creating symbol: %w", err)
}
sym.SetExpression(alias.Expression)
return []any{sym}, nil
return []ast.Node{&symbol{Symbol: sym}}, nil
}

func parseLabel(asm *parseAST, label ast.Label) ([]any, error) {
func parseLabel(asm *parseAST, label ast.Label) ([]ast.Node, error) {
sym, err := scope.NewSymbol(asm.currentScope, label.Name, scope.LabelType)
if err != nil {
return nil, fmt.Errorf("creating symbol: %w", err)
}

return []any{sym}, nil
return []ast.Node{&symbol{Symbol: sym}}, nil
}

func parseInstruction(astInstruction ast.Instruction) ([]any, error) {
func parseInstruction(astInstruction ast.Instruction) ([]ast.Node, error) {
if astInstruction.Modifier != nil {
return nil, fmt.Errorf("unexpected modifier %v", astInstruction.Modifier)
}
Expand All @@ -283,10 +268,10 @@ func parseInstruction(astInstruction ast.Instruction) ([]any, error) {
return nil, fmt.Errorf("unexpected argument type %T", arg)
}

return []any{ins}, nil
return []ast.Node{ins}, nil
}

func parseInclude(asm *parseAST, inc ast.Include) ([]any, error) {
func parseInclude(asm *parseAST, inc ast.Include) ([]ast.Node, error) {
if !inc.Binary {
return nil, errors.New("non binary includes are currently not supported") // TODO implement
}
Expand All @@ -300,15 +285,15 @@ func parseInclude(asm *parseAST, inc ast.Include) ([]any, error) {
dat := &data{size: expression.New()}
dat.size.SetValue(1)
dat.values = append(dat.values, b)
return []any{dat}, nil
return []ast.Node{dat}, nil
}

func parseVariable(astVar ast.Variable) []any {
func parseVariable(astVar ast.Variable) []ast.Node {
v := &variable{v: astVar}
return []any{v}
return []ast.Node{v}
}

func parseFunction(asm *parseAST, fun ast.Function) ([]any, error) {
func parseFunction(asm *parseAST, fun ast.Function) ([]ast.Node, error) {
sym, err := scope.NewSymbol(asm.currentScope, fun.Name, scope.FunctionType)
if err != nil {
return nil, fmt.Errorf("creating symbol: %w", err)
Expand All @@ -319,10 +304,10 @@ func parseFunction(asm *parseAST, fun ast.Function) ([]any, error) {
scope: asm.currentScope,
}

return []any{newScope, sym}, nil
return []ast.Node{newScope, &symbol{Symbol: sym}}, nil
}

func parseFunctionEnd(asm *parseAST, _ ast.FunctionEnd) ([]any, error) {
func parseFunctionEnd(asm *parseAST, _ ast.FunctionEnd) ([]ast.Node, error) {
parentScope := asm.currentScope.Parent()
if parentScope == nil {
return nil, errors.New("unexpected function end, no parent scope found")
Expand All @@ -334,10 +319,10 @@ func parseFunctionEnd(asm *parseAST, _ ast.FunctionEnd) ([]any, error) {
scope: asm.currentScope,
}

return []any{newScope}, nil
return []ast.Node{newScope}, nil
}

func parseMacro(astMacro ast.Macro) ([]any, error) {
func parseMacro(astMacro ast.Macro) ([]ast.Node, error) {
mac := macro{
name: astMacro.Name,
arguments: map[string]int{},
Expand All @@ -352,5 +337,5 @@ func parseMacro(astMacro ast.Macro) ([]any, error) {
mac.arguments[argument] = i
}

return []any{mac}, nil
return []ast.Node{mac}, nil
}
8 changes: 4 additions & 4 deletions assembler/process_macros_step.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
// processMacrosStep processes macro usages and replace them by the macro nodes.
func processMacrosStep(asm *Assembler) error {
for i, seg := range asm.segmentsOrder {
segmentNodesResolved := make([]any, 0, len(seg.nodes))
segmentNodesResolved := make([]ast.Node, 0, len(seg.nodes))

for _, node := range seg.nodes {
switch n := node.(type) {
Expand Down Expand Up @@ -40,7 +40,7 @@ func processMacrosStep(asm *Assembler) error {
return nil
}

func resolveMacroUsage(asm *Assembler, id ast.Identifier) ([]any, error) {
func resolveMacroUsage(asm *Assembler, id ast.Identifier) ([]ast.Node, error) {
mac, ok := asm.macros[id.Name]
if !ok {
return nil, fmt.Errorf("unexpected identifier '%s' found", id.Name)
Expand Down Expand Up @@ -77,7 +77,7 @@ func resolveMacroUsage(asm *Assembler, id ast.Identifier) ([]any, error) {
return macroTokensToAStNodes(asm, mac.tokens)
}

func macroTokensToAStNodes(asm *Assembler, tokens []token.Token) ([]any, error) {
func macroTokensToAStNodes(asm *Assembler, tokens []token.Token) ([]ast.Node, error) {
// convert the adjusted tokens to AST nodes
par := parser.NewWithTokens(asm.cfg.Arch, tokens)
astNodes, err := par.TokensToAstNodes()
Expand All @@ -93,7 +93,7 @@ func macroTokensToAStNodes(asm *Assembler, tokens []token.Token) ([]any, error)
}

// process the AST nodes
var result []any
var result []ast.Node
for _, node := range astNodes {
nodes, err := parseASTNode(p, node)
if err != nil {
Expand Down
9 changes: 6 additions & 3 deletions assembler/segment.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package assembler

import "github.com/retroenv/retroasm/assembler/config"
import (
"github.com/retroenv/retroasm/assembler/config"
"github.com/retroenv/retroasm/parser/ast"
)

type segment struct {
config *config.Segment
nodes []any
nodes []ast.Node
}

func (seg *segment) addNode(node any) {
func (seg *segment) addNode(node ast.Node) {
seg.nodes = append(seg.nodes, node)
}
Loading

0 comments on commit 53a1a87

Please sign in to comment.