<commit_before>/* © 2012 <NAME>
 * This file is made available under the terms of the two-clause BSD
 * license. See the file COPYING.BSD in the distribution directory for the
 * full license text.
 */

package com.cowlark.cowbel.backend.c;

import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import com.cowlark.cowbel.ast.AbstractScopeConstructorNode;
import com.cowlark.cowbel.ast.ExternStatementNode;
import com.cowlark.cowbel.ast.FunctionDefinitionNode;
import com.cowlark.cowbel.ast.FunctionHeaderNode;
import com.cowlark.cowbel.ast.ParameterDeclarationListNode;
import com.cowlark.cowbel.ast.ParameterDeclarationNode;
import com.cowlark.cowbel.ast.RecursiveASTVisitor;
import com.cowlark.cowbel.ast.StringConstantNode;
import com.cowlark.cowbel.backend.Backend;
import com.cowlark.cowbel.core.BasicBlock;
import com.cowlark.cowbel.core.Callable;
import com.cowlark.cowbel.core.Compiler;
import com.cowlark.cowbel.core.Constructor;
import com.cowlark.cowbel.core.Function;
import com.cowlark.cowbel.core.Method;
import com.cowlark.cowbel.errors.CompilationException;
import com.cowlark.cowbel.errors.DowncastingExternsNotImplementedYet;
import com.cowlark.cowbel.errors.InvalidExternTemplate;
import com.cowlark.cowbel.instructions.BooleanConstantInstruction;
import com.cowlark.cowbel.instructions.ConstructInstruction;
import com.cowlark.cowbel.instructions.CreateObjectReferenceInstruction;
import com.cowlark.cowbel.instructions.DirectFunctionCallInstruction;
import com.cowlark.cowbel.instructions.ExternFunctionCallInstruction;
import com.cowlark.cowbel.instructions.ExternInstruction;
import com.cowlark.cowbel.instructions.FunctionExitInstruction;
import com.cowlark.cowbel.instructions.GotoInstruction;
import com.cowlark.cowbel.instructions.HasInputVariables;
import com.cowlark.cowbel.instructions.HasOutputVariables;
import com.cowlark.cowbel.instructions.IfInstruction;
import com.cowlark.cowbel.instructions.Instruction;
import com.cowlark.cowbel.instructions.IntegerConstantInstruction;
import com.cowlark.cowbel.instructions.MethodCallInstruction;
import com.cowlark.cowbel.instructions.RealConstantInstruction;
import com.cowlark.cowbel.instructions.StringConstantInstruction;
import com.cowlark.cowbel.instructions.VarCopyInstruction;
import com.cowlark.cowbel.interfaces.HasNode;
import com.cowlark.cowbel.interfaces.HasTypeRef;
import com.cowlark.cowbel.interfaces.IsNode;
import com.cowlark.cowbel.symbols.Symbol;
import com.cowlark.cowbel.symbols.Variable;
import com.cowlark.cowbel.types.AbstractConcreteType;
import com.cowlark.cowbel.types.ExternObjectConcreteType;
import com.cowlark.cowbel.types.InferenceFailedConcreteType;
import com.cowlark.cowbel.types.InterfaceConcreteType;
import com.cowlark.cowbel.types.ObjectConcreteType;

public class CBackend extends Backend
{
	private static Charset UTF8 = Charset.forName("utf-8");
	
	private HashMap<AbstractConcreteType, String> _typeTypes =
		new HashMap<AbstractConcreteType, String>();
	private HashMap<AbstractConcreteType, String> _typeLabels =
		new HashMap<AbstractConcreteType, String>();
	private HashMap<Method, String> _methodLabels =
		new HashMap<Method, String>();
	private HashMap<Constructor, String> _constructorTypes =
		new HashMap<Constructor, String>();
	private HashMap<Constructor, String> _constructorLabels =
		new HashMap<Constructor, String>();
	private HashMap<Function, String> _functionLabels =
		new HashMap<Function, String>();
	private HashMap<Symbol, String> _symbolLabels =
		new HashMap<Symbol, String>();
	private HashMap<BasicBlock, String> _bbLabels =
		new HashMap<BasicBlock, String>();
	private HashMap<StringConstantNode, String> _stringLabels =
		new HashMap<StringConstantNode, String>();
	
	private boolean _inputparamsinvalid;
	private int _funcid;
	private String _returnvalue;
	
	public CBackend(Compiler compiler, OutputStream os)
    {
	    super(compiler, os);
    }
	
	@Override
	public void setMainFunction(Function mainFunction)
	{
		_functionLabels.put(mainFunction, "cowbel_main");
	}
	
	@Override
	public void prologue() throws CompilationException
	{
		Compiler compiler = getCompiler();
        InputStream is = getClass().getResourceAsStream("prologue.h");
        print(is);
	    
        /* Find any #include externs. */
        
	    compiler.visit(
	    		new RecursiveASTVisitor()
	    		{
	    			@Override
                    public void visit(FunctionDefinitionNode node) throws CompilationException
	    			{
	    			};
	    			
	    			@Override
                    public void visit(ExternStatementNode node) throws CompilationException
	    			{
	    				String template = node.getTemplate();
	    				
	    				if (template.startsWith("#include"))
	    				{
	    					if (template.contains("\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009"))
	    						throw new InvalidExternTemplate(node);
	    					
	    					print(template);
	    					print('\n');
	    				}
	    			};
	    		}
	    	);
	    print("\n");

	    /* Emit prototypes for interfaces, objects and constructors. */
	    
		for (InterfaceConcreteType t : InterfaceConcreteType.getAllInterfaceTypes())
		{
			print(ctypes(t));
			print(";\n");
		}
		for (ObjectConcreteType t : ObjectConcreteType.getAllObjectTypes())
		{
			print(ctypes(t));
			print(";\n");
		}
	    for (Constructor c : Constructor.getAllConstructors())
	    {
	    	print(ctype(c));
	    	print(";\n");
	    }
	    
	    /* Emit prototypes for functions. */
	    
	    for (Function f : Function.getAllFunctions())
	    {
	    	function_header(f);
	    	print(";\n");
	    }
	    print("\n");
	    
	    /* Emit string constants. */
	    
	    compiler.visit(
	    		new RecursiveASTVisitor()
	    		{
	    			@Override
                    public void visit(FunctionDefinitionNode node) throws CompilationException
	    			{
	    			};
	    			
	    			@Override
                    public void visit(StringConstantNode node)
	    				throws CompilationException
	    			{
	    				byte[] bytes = node.getValue().getBytes(UTF8);
	    				
	    				String id = "S" + clabel(node);
	    				print("static const char ");
	    				print(id);
	    				print("[] = {");
	    				boolean first = true;
	    				for (byte b : bytes)
	    				{
	    					if (!first)
	    						print(", ");
	    					first = false;

	    					print((int) b);
	    				}
	    				print("};\n");
	    				
	    				print("static s_string_t ");
	    				print(clabel(node));
	    				print(" = { NULL, NULL, ");
	    				print(id);
	    				print(", ");
	    				print(bytes.length);
	    				print(", ");
	    				print(bytes.length);
	    				print(", NULL};\n");
	    			}<commit_msg>Prepopulate the cdata part of constant strings.<commit_after>/* © 2012 <NAME>
 * This file is made available under the terms of the two-clause BSD
 * license. See the file COPYING.BSD in the distribution directory for the
 * full license text.
 */

package com.cowlark.cowbel.backend.c;

import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import com.cowlark.cowbel.ast.AbstractScopeConstructorNode;
import com.cowlark.cowbel.ast.ExternStatementNode;
import com.cowlark.cowbel.ast.FunctionDefinitionNode;
import com.cowlark.cowbel.ast.FunctionHeaderNode;
import com.cowlark.cowbel.ast.ParameterDeclarationListNode;
import com.cowlark.cowbel.ast.ParameterDeclarationNode;
import com.cowlark.cowbel.ast.RecursiveASTVisitor;
import com.cowlark.cowbel.ast.StringConstantNode;
import com.cowlark.cowbel.backend.Backend;
import com.cowlark.cowbel.core.BasicBlock;
import com.cowlark.cowbel.core.Callable;
import com.cowlark.cowbel.core.Compiler;
import com.cowlark.cowbel.core.Constructor;
import com.cowlark.cowbel.core.Function;
import com.cowlark.cowbel.core.Method;
import com.cowlark.cowbel.errors.CompilationException;
import com.cowlark.cowbel.errors.DowncastingExternsNotImplementedYet;
import com.cowlark.cowbel.errors.InvalidExternTemplate;
import com.cowlark.cowbel.instructions.BooleanConstantInstruction;
import com.cowlark.cowbel.instructions.ConstructInstruction;
import com.cowlark.cowbel.instructions.CreateObjectReferenceInstruction;
import com.cowlark.cowbel.instructions.DirectFunctionCallInstruction;
import com.cowlark.cowbel.instructions.ExternFunctionCallInstruction;
import com.cowlark.cowbel.instructions.ExternInstruction;
import com.cowlark.cowbel.instructions.FunctionExitInstruction;
import com.cowlark.cowbel.instructions.GotoInstruction;
import com.cowlark.cowbel.instructions.HasInputVariables;
import com.cowlark.cowbel.instructions.HasOutputVariables;
import com.cowlark.cowbel.instructions.IfInstruction;
import com.cowlark.cowbel.instructions.Instruction;
import com.cowlark.cowbel.instructions.IntegerConstantInstruction;
import com.cowlark.cowbel.instructions.MethodCallInstruction;
import com.cowlark.cowbel.instructions.RealConstantInstruction;
import com.cowlark.cowbel.instructions.StringConstantInstruction;
import com.cowlark.cowbel.instructions.VarCopyInstruction;
import com.cowlark.cowbel.interfaces.HasNode;
import com.cowlark.cowbel.interfaces.HasTypeRef;
import com.cowlark.cowbel.interfaces.IsNode;
import com.cowlark.cowbel.symbols.Symbol;
import com.cowlark.cowbel.symbols.Variable;
import com.cowlark.cowbel.types.AbstractConcreteType;
import com.cowlark.cowbel.types.ExternObjectConcreteType;
import com.cowlark.cowbel.types.InferenceFailedConcreteType;
import com.cowlark.cowbel.types.InterfaceConcreteType;
import com.cowlark.cowbel.types.ObjectConcreteType;

public class CBackend extends Backend
{
	private static Charset UTF8 = Charset.forName("utf-8");
	
	private HashMap<AbstractConcreteType, String> _typeTypes =
		new HashMap<AbstractConcreteType, String>();
	private HashMap<AbstractConcreteType, String> _typeLabels =
		new HashMap<AbstractConcreteType, String>();
	private HashMap<Method, String> _methodLabels =
		new HashMap<Method, String>();
	private HashMap<Constructor, String> _constructorTypes =
		new HashMap<Constructor, String>();
	private HashMap<Constructor, String> _constructorLabels =
		new HashMap<Constructor, String>();
	private HashMap<Function, String> _functionLabels =
		new HashMap<Function, String>();
	private HashMap<Symbol, String> _symbolLabels =
		new HashMap<Symbol, String>();
	private HashMap<BasicBlock, String> _bbLabels =
		new HashMap<BasicBlock, String>();
	private HashMap<StringConstantNode, String> _stringLabels =
		new HashMap<StringConstantNode, String>();
	
	private boolean _inputparamsinvalid;
	private int _funcid;
	private String _returnvalue;
	
	public CBackend(Compiler compiler, OutputStream os)
    {
	    super(compiler, os);
    }
	
	@Override
	public void setMainFunction(Function mainFunction)
	{
		_functionLabels.put(mainFunction, "cowbel_main");
	}
	
	@Override
	public void prologue() throws CompilationException
	{
		Compiler compiler = getCompiler();
        InputStream is = getClass().getResourceAsStream("prologue.h");
        print(is);
	    
        /* Find any #include externs. */
        
	    compiler.visit(
	    		new RecursiveASTVisitor()
	    		{
	    			@Override
                    public void visit(FunctionDefinitionNode node) throws CompilationException
	    			{
	    			};
	    			
	    			@Override
                    public void visit(ExternStatementNode node) throws CompilationException
	    			{
	    				String template = node.getTemplate();
	    				
	    				if (template.startsWith("#include"))
	    				{
	    					if (template.contains("\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009"))
	    						throw new InvalidExternTemplate(node);
	    					
	    					print(template);
	    					print('\n');
	    				}
	    			};
	    		}
	    	);
	    print("\n");

	    /* Emit prototypes for interfaces, objects and constructors. */
	    
		for (InterfaceConcreteType t : InterfaceConcreteType.getAllInterfaceTypes())
		{
			print(ctypes(t));
			print(";\n");
		}
		for (ObjectConcreteType t : ObjectConcreteType.getAllObjectTypes())
		{
			print(ctypes(t));
			print(";\n");
		}
	    for (Constructor c : Constructor.getAllConstructors())
	    {
	    	print(ctype(c));
	    	print(";\n");
	    }
	    
	    /* Emit prototypes for functions. */
	    
	    for (Function f : Function.getAllFunctions())
	    {
	    	function_header(f);
	    	print(";\n");
	    }
	    print("\n");
	    
	    /* Emit string constants. */
	    
	    compiler.visit(
	    		new RecursiveASTVisitor()
	    		{
	    			@Override
                    public void visit(FunctionDefinitionNode node) throws CompilationException
	    			{
	    			};
	    			
	    			@Override
                    public void visit(StringConstantNode node)
	    				throws CompilationException
	    			{
	    				byte[] bytes = node.getValue().getBytes(UTF8);
	    				
	    				String id = "S" + clabel(node);
	    				print("static const char ");
	    				print(id);
	    				print("[] = {");
	    				boolean first = true;
	    				for (byte b : bytes)
	    				{
	    					if (!first)
	    						print(", ");
	    					first = false;

	    					print((int) b);
	    				}
	    				if (!first)
	    					print(", ");
	    				print("0};\n");
	    				
	    				print("static s_string_t ");
	    				print(clabel(node));
	    				print(" = { NULL, NULL, ");
	    				print(id);
	    				print(", ");
	    				print(bytes.length);
	    				print(", ");
	    				print(bytes.length);
	    				print(", ");
	    				print(id);
	    				print("};\n");
	    			}
{'fraction_non_alphanumeric': 0.10632205007709818, 'fraction_numerical': 0.006975548865555474, 'mean_word_length': 3.3893006767644214, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '126117', 'n_tokens_mistral': 4701, 'n_tokens_neox': 4299, 'n_words': 752}