Esempio n. 1
0
func (sw *SourceWriter) writeInstruction(n *parser.Instruction) {
	chld := n.Children()
	name := chld[0].(*parser.Name)

	if parser.IsBranch(name.Data) {
		sw.nestLevel++
	} else {
		sw.nestLevel = 1
	}

	sw.writeList(chld)
}
Esempio n. 2
0
func (*OptShorthand) Process(ast *parser.AST) (err error) {
	var instr *parser.Instruction
	var num parser.NumericNode
	var argv []parser.Node
	var name *parser.Name
	var word cpu.Word
	var ok bool

	nodes := ast.Root.Children()

	for i := range nodes {
		if instr, ok = nodes[i].(*parser.Instruction); !ok {
			continue
		}

		argv = instr.Children()
		name = argv[0].(*parser.Name)

		if name.Data != "ife" && name.Data != "ifn" {
			continue
		}

		if len(argv) < 3 {
			continue
		}

		num, ok = argv[1].(*parser.Expression).Children()[0].(parser.NumericNode)
		if !ok {
			continue
		}

		if word, err = num.Parse(); err != nil {
			return err
		}

		if ok && (word == 0xffff || word <= 0x1e) {
			argv[1], argv[2] = argv[2], argv[1]
		}
	}

	return
}
Esempio n. 3
0
File: funcs.go Progetto: DanB91/dcpu
// fixFunctionReturns finds 'return' instructions and replaces them
// with appropriate `set pc, $__<name>_epilog` versions.
func fixFunctionReturns(ast *parser.AST, f *parser.Function) {
	var instr *parser.Instruction
	var expr *parser.Expression
	var file, line, col int
	var code []parser.Node
	var ok bool

	name := f.Children()[0].(*parser.Name)
	exitLabel := "$__" + name.Data + "_epilog"
	list := f.Children()[1:]

	for i := range list {
		if instr, ok = list[i].(*parser.Instruction); !ok {
			continue
		}

		code = instr.Children()
		name = code[0].(*parser.Name)
		if name.Data != "return" {
			continue
		}

		file, line, col = instr.File(), instr.Line(), instr.Col()
		name.Data = "set"
		code = append(code, nil, nil)

		expr = parser.NewExpression(file, line, col)
		expr.SetChildren([]parser.Node{
			parser.NewName(file, line, col, "pc"),
		})
		code[1] = expr

		expr = parser.NewExpression(file, line, col)
		expr.SetChildren([]parser.Node{
			parser.NewName(file, line, col, exitLabel),
		})
		code[2] = expr

		instr.SetChildren(code)
	}
}
Esempio n. 4
0
File: const.go Progetto: DanB91/dcpu
// parseConstants finds constant definitions and references to them.
// It replaces the references with the nodes denoting the value of
// the respective constants.
func parseConstants(ast *parser.AST, list []parser.Node) (out []parser.Node, err error) {
	var instr *parser.Instruction
	var expr *parser.Expression
	var name *parser.Name
	var ok bool

	consts := make(map[string][]parser.Node)

	for i := 0; i < len(list); i++ {
		if instr, ok = list[i].(*parser.Instruction); !ok {
			continue
		}

		name = instr.Children()[0].(*parser.Name)
		if name.Data != "equ" {
			continue
		}

		expr = instr.Children()[1].(*parser.Expression)
		name = expr.Children()[0].(*parser.Name)

		if _, ok = consts[name.Data]; ok {
			return nil, NewBuildError(
				ast.Files[instr.File()], instr.Line(), instr.Col(),
				"Duplicate constant %q.", name.Data)
		}

		expr = instr.Children()[2].(*parser.Expression)
		consts[name.Data] = expr.Children()

		// Remove constant node from AST.
		copy(list[i:], list[i+1:])
		list = list[:len(list)-1]
		i--
	}

	for k, v := range consts {
		list = replaceConstantRef(list, k, v)
	}

	return list, nil
}