/** * Copyright 2012 Tobias Gierke <tobias.gierke@code-sourcery.de> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.codesourcery.jasm16.compiler; import java.io.IOException; import java.util.Collections; import java.util.List; import de.codesourcery.jasm16.ast.AST; import de.codesourcery.jasm16.ast.ASTUtils; import de.codesourcery.jasm16.ast.InvokeMacroNode; import de.codesourcery.jasm16.compiler.phases.ExpandMacrosPhase; import de.codesourcery.jasm16.parser.Parser; import de.codesourcery.jasm16.parser.TestHelper; import de.codesourcery.jasm16.utils.FormattingVisitor; public class ExpandMacrosPhaseTest extends TestHelper { public void testExpandMacroWithNoArguments() throws IOException { final String macroBody = "ADD a,1\n"+ "ADD b,2"; final String source =".macro brk\n"+ macroBody+"\n"+ ".endmacro\n"+ "brk"; ICompilationUnit unit = CompilationUnit.createInstance("dummy",source); ICompilationContext compContext = createCompilationContext( unit ); AST ast = new Parser(this).parse( compContext ); unit.setAST( ast ); if ( ast.hasErrors() ) { for ( IMarker m : unit.getErrors() ) { System.out.println("ERROR: "+m); } } assertFalse( "AST has errors?" , unit.getAST().hasErrors() ); assertFalse( unit.hasErrors() ); assertNotNull( unit.getAST() ); System.out.println("=== Before expansion"); ASTUtils.visitInOrder( ast , new FormattingVisitor( compContext , true ) ); new ExpandMacrosPhase().execute( Collections.singletonList( unit ) , debugInfo,symbolTable , NOP_WRITER , new CompilationListener(), RESOURCE_RESOLVER, OPTIONS, new MyResolver(unit) ); assertFalse( ast.hasErrors() ); assertFalse( unit.hasErrors() ); System.out.println("=== After expansion"); ASTUtils.visitInOrder( ast , new FormattingVisitor( compContext , true ) ); List<InvokeMacroNode> startNode = ASTUtils.getNodesByType( ast , InvokeMacroNode.class , true ); String expandedBody = ExpandMacrosPhase.expandInvocation( startNode.get(0) , unit ); // System.out.println("\n\nExpanded body:\n>"+expandedBody+"<"); assertEquals( macroBody , expandedBody ); System.out.println("\n\n============\nAST\n=========\n"); ASTUtils.debugPrintTextRegions(ast, source , unit ); } public void testExpandMacroWithOneArgument() throws IOException { final String source =".macro inc(value)\n"+ " ADD a,value\n"+ ".endmacro\n"+ "inc(10)"; ICompilationUnit unit = CompilationUnit.createInstance("dummy",source); ICompilationContext compContext = createCompilationContext( unit ); AST ast = new Parser(this).parse( compContext ); unit.setAST( ast ); if ( ast.hasErrors() ) { for ( IMarker m : unit.getErrors() ) { System.out.println("ERROR: "+m); } } assertFalse( "AST has errors?" , unit.getAST().hasErrors() ); assertFalse( unit.hasErrors() ); assertNotNull( unit.getAST() ); System.out.println("=== Before expansion"); ASTUtils.visitInOrder( ast , new FormattingVisitor( compContext , true ) ); new ExpandMacrosPhase().execute( Collections.singletonList( unit ) , debugInfo,symbolTable , NOP_WRITER , new CompilationListener(), RESOURCE_RESOLVER, OPTIONS, new MyResolver(unit) ); assertFalse( ast.hasErrors() ); assertFalse( unit.hasErrors() ); System.out.println("=== After expansion"); ASTUtils.visitInOrder( ast , new FormattingVisitor( compContext , true ) ); } public void testExpandMacroWithTwoArguments() throws IOException { final String source =".macro inc(value1,value2)\n"+ " ADD value1,value2\n"+ ".endmacro\n"+ "inc(A,2)"; ICompilationUnit unit = CompilationUnit.createInstance("dummy",source); ICompilationContext compContext = createCompilationContext( unit ); AST ast = new Parser(this).parse( compContext ); unit.setAST( ast ); if ( ast.hasErrors() ) { for ( IMarker m : unit.getErrors() ) { System.out.println("ERROR: "+m); } } assertFalse( "AST has errors?" , unit.getAST().hasErrors() ); assertFalse( unit.hasErrors() ); assertNotNull( unit.getAST() ); System.out.println("=== Before expansion"); ASTUtils.visitInOrder( ast , new FormattingVisitor( compContext , true ) ); new ExpandMacrosPhase().execute( Collections.singletonList( unit ) , debugInfo,symbolTable , NOP_WRITER , new CompilationListener(), RESOURCE_RESOLVER, OPTIONS, new MyResolver(unit) ); assertFalse( ast.hasErrors() ); assertFalse( unit.hasErrors() ); System.out.println("=== After expansion"); ASTUtils.visitInOrder( ast , new FormattingVisitor( compContext , true ) ); } public void testExpandMultipleMacros() throws IOException { final String source="\n" + "\n" + ".equ vram 0x8000\n" + ".equ graphics_enable 0x9040\n" + "\n" + ".macro rts \n" + " SET PC, POP\n" + ".endmacro\n" + "\n" + ".macro neg(what)\n" + " xor what , 0xFFFF\n" + " add what , 1\n" + ".endmacro\n" + "\n" + ".macro negd(lo,hi)\n" + " xor lo , 0xFFFF\n" + " xor hi , 0xFFFF\n" + " add lo , 1\n" + " add hi , ex\n" + ".endmacro\n" + "\n" + ".macro shld(lo,hi,amount)\n" + " shl hi , amount\n" + " shl lo , amount\n" + " bor hi , ex\n" + ".endmacro\n" + "\n" + ".macro shrd(lo,hi,amount)\n" + " shr lo , amount\n" + " and lo , 0x7FFF\n" + " shr hi , amount\n" + " and hi , 0x7FFF\n" + " bor lo , ex\n" + ".endmacro\n" + "\n" + ".macro addd(lo,hi,rhslo,rhshi)\n" + " add hi , rhshi\n" + " add lo , rhslo\n" + " add hi , ex\n" + ".endmacro\n" + "\n" + ".macro subd(lo,hi,rhslo,rhshi)\n" + " sub hi , rhshi\n" + " sub lo , rhslo\n" + " add hi , ex\n" + ".endmacro\n" + "\n" + ".macro rol (var,n)\n" + " shr var , n\n" + " bor var , ex\n" + ".endmacro\n" + "\n\n"+ " rol(A,5)"; ICompilationUnit unit = CompilationUnit.createInstance("dummy",source); ICompilationContext compContext = createCompilationContext( unit ); AST ast = new Parser(this).parse( compContext ); unit.setAST( ast ); if ( ast.hasErrors() ) { for ( IMarker m : unit.getErrors() ) { System.out.println("ERROR: "+m); } } assertFalse( "AST has errors?" , unit.getAST().hasErrors() ); assertFalse( unit.hasErrors() ); assertNotNull( unit.getAST() ); System.out.println("=== Before expansion"); ASTUtils.visitInOrder( ast , new FormattingVisitor( compContext , true ) ); new ExpandMacrosPhase().execute( Collections.singletonList( unit ) , debugInfo,symbolTable , NOP_WRITER , new CompilationListener(), RESOURCE_RESOLVER, OPTIONS, new MyResolver(unit) ); assertFalse( ast.hasErrors() ); assertFalse( unit.hasErrors() ); System.out.println("=== After expansion"); ASTUtils.visitInOrder( ast , new FormattingVisitor( compContext , true ) ); } }