Skip to content

Commit

Permalink
Improvements & refactoring & better testing
Browse files Browse the repository at this point in the history
  • Loading branch information
BBpezsgo committed Dec 31, 2023
1 parent a3dbd24 commit c928a01
Show file tree
Hide file tree
Showing 159 changed files with 1,842 additions and 1,165 deletions.
1 change: 1 addition & 0 deletions DevelopmentEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public static bool Start(string[] args)
"--hide-system",
// "--dont-optimize",
"--console-gui",
// "--print-instructions",
"--brainfuck",
// "--il",
// "--asm",
Expand Down
254 changes: 227 additions & 27 deletions Entry.cs

Large diffs are not rendered by default.

35 changes: 1 addition & 34 deletions Source/ASM/Assembler.cs
Original file line number Diff line number Diff line change
@@ -1,40 +1,7 @@
using System;
using System.IO;
using System.IO;

namespace LanguageCore.ASM
{
public class ProcessException : Exception
{
readonly string processName;
readonly int exitCode;
readonly string stdOutput;
readonly string stdError;

public override string Message => $"Process \"{processName}\" exited with code {exitCode}";
public string StandardOutput => stdOutput;
public string StandardError => stdError;

public ProcessException(string processName, int exitCode, string stdOutput, string stdError) : base()
{
this.processName = processName;
this.exitCode = exitCode;
this.stdOutput = stdOutput;
this.stdError = stdError;
}
}

public class ProcessNotStartedException : Exception
{
readonly string processName;

public override string Message => $"Failed to start process \"{processName}\"";

public ProcessNotStartedException(string processName) : base()
{
this.processName = processName;
}
}

public static class Assembler
{
public static void Assemble(string asmSourceCode, string outputFile)
Expand Down
101 changes: 56 additions & 45 deletions Source/ASM/CodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ public struct AsmGeneratorSettings

public struct AsmGeneratorResult
{
public Warning[] Warnings;
public Error[] Errors;

public string AssemblyCode;
}

Expand All @@ -61,15 +58,9 @@ public class CodeGeneratorForAsm : CodeGenerator

#endregion

public CodeGeneratorForAsm(CompilerResult compilerResult, AsmGeneratorSettings settings) : base()
public CodeGeneratorForAsm(CompilerResult compilerResult, AsmGeneratorSettings settings, AnalysisCollection? analysisCollection) : base(compilerResult, LanguageCore.Compiler.GeneratorSettings.Default, analysisCollection)
{
this.GeneratorSettings = settings;
this.CompiledFunctions = compilerResult.Functions;
this.CompiledOperators = compilerResult.Operators;
this.CompiledClasses = compilerResult.Classes;
this.CompiledStructs = compilerResult.Structs;
this.CompiledEnums = compilerResult.Enums;
this.CompiledMacros = compilerResult.Macros;
this.Builder = new AssemblyCode();

this.FunctionLabels = new List<(CompiledFunction Function, string Label)>();
Expand Down Expand Up @@ -102,7 +93,24 @@ bool TryGetFunctionLabel(CompiledFunction function, [NotNullWhen(true)] out stri
protected override void StackLoad(ValueAddress address)
{
if (address.IsReference)
{ throw new NotImplementedException(); }
{
switch (address.AddressingMode)
{
case AddressingMode.Absolute:
Builder.CodeBuilder.AppendInstruction(ASM.Instruction.MOV, Registers.EAX, $"DWORD[{(address.Address + 1) * 4}]");
Builder.CodeBuilder.AppendInstruction(ASM.Instruction.PUSH, Registers.EAX);
return;
case AddressingMode.Runtime:
throw new NotImplementedException();
case AddressingMode.BasePointerRelative:
Builder.CodeBuilder.AppendInstruction(ASM.Instruction.MOV, Registers.EAX, $"DWORD[{Registers.EBP}{(address.Address > 0 ? "-" : "+")}{(Math.Abs(address.Address) + 1) * 4}]");
Builder.CodeBuilder.AppendInstruction(ASM.Instruction.PUSH, Registers.EAX);
return;
case AddressingMode.StackRelative:
throw new NotImplementedException();
default: throw new UnreachableException();
}
}

if (address.InHeap)
{ throw new NotImplementedException($"HEAP stuff generator isn't implemented for assembly"); }
Expand All @@ -128,7 +136,24 @@ protected override void StackLoad(ValueAddress address)
protected override void StackStore(ValueAddress address)
{
if (address.IsReference)
{ throw new NotImplementedException(); }
{
switch (address.AddressingMode)
{
case AddressingMode.Absolute:
Builder.CodeBuilder.AppendInstruction(ASM.Instruction.POP, Registers.EAX);
Builder.CodeBuilder.AppendInstruction(ASM.Instruction.MOV, $"DWORD[{(address.Address + 1) * 4}]", Registers.EAX);
return;
case AddressingMode.Runtime:
throw new NotImplementedException();
case AddressingMode.BasePointerRelative:
Builder.CodeBuilder.AppendInstruction(ASM.Instruction.POP, Registers.EAX);
Builder.CodeBuilder.AppendInstruction(ASM.Instruction.MOV, $"DWORD[{Registers.EBP}{(address.Address > 0 ? "-" : "+")}{(Math.Abs(address.Address) + 1) * 4}]", Registers.EAX);
return;
case AddressingMode.StackRelative:
throw new NotImplementedException();
default: throw new UnreachableException();
}
}

if (address.InHeap)
{ throw new NotImplementedException($"HEAP stuff generator isn't implemented for assembly"); }
Expand Down Expand Up @@ -343,7 +368,7 @@ CleanupItem GenerateCodeForVariable(VariableDeclaration newVariable)
{
if (CompiledVariables[i].VariableName.Content == newVariable.VariableName.Content)
{
Warnings.Add(new Warning($"Variable \"{CompiledVariables[i].VariableName}\" already defined", CompiledVariables[i].VariableName, CurrentFile));
AnalysisCollection?.Warnings.Add(new Warning($"Variable \"{CompiledVariables[i].VariableName}\" already defined", CompiledVariables[i].VariableName, CurrentFile));
return CleanupItem.Null;
}
}
Expand Down Expand Up @@ -438,17 +463,8 @@ void GenerateCodeForSetter(Identifier statement, StatementWithValue value)

GenerateCodeForStatement(value);

if (parameter.IsRef)
{
throw new NotImplementedException();
}
else
{
ValueAddress offset = GetBaseAddress(parameter);
StackStore(offset);
}

throw new NotImplementedException();
ValueAddress offset = GetBaseAddress(parameter);
StackStore(offset);
}
else if (GetVariable(statement.Token.Content, out CompiledVariable? variable))
{
Expand Down Expand Up @@ -519,12 +535,12 @@ Stack<ParameterCleanupItem> GenerateCodeForParameterPassing(FunctionCall functio
if (StatementCanBeDeallocated(passedParameter, out bool explicitDeallocate))
{
if (explicitDeallocate && !canDeallocate)
{ Warnings.Add(new Warning($"Can not deallocate this value: parameter definition does not have a \"{"temp"}\" modifier", passedParameter, CurrentFile)); }
{ AnalysisCollection?.Warnings.Add(new Warning($"Can not deallocate this value: parameter definition does not have a \"{"temp"}\" modifier", passedParameter, CurrentFile)); }
}
else
{
if (explicitDeallocate)
{ Warnings.Add(new Warning($"Can not deallocate this value", passedParameter, CurrentFile)); }
{ AnalysisCollection?.Warnings.Add(new Warning($"Can not deallocate this value", passedParameter, CurrentFile)); }
canDeallocate = false;
}

Expand Down Expand Up @@ -556,12 +572,12 @@ Stack<ParameterCleanupItem> GenerateCodeForParameterPassing(FunctionCall functio
if (StatementCanBeDeallocated(passedParameter, out bool explicitDeallocate))
{
if (explicitDeallocate)
{ Warnings.Add(new Warning($"Can not deallocate this value: parameter definition does not have a \"{"temp"}\" modifier", passedParameter, CurrentFile)); }
{ AnalysisCollection?.Warnings.Add(new Warning($"Can not deallocate this value: parameter definition does not have a \"{"temp"}\" modifier", passedParameter, CurrentFile)); }
}
else
{
if (explicitDeallocate)
{ Warnings.Add(new Warning($"Can not deallocate this value", passedParameter, CurrentFile)); }
{ AnalysisCollection?.Warnings.Add(new Warning($"Can not deallocate this value", passedParameter, CurrentFile)); }
}

GenerateCodeForStatement(passedParameter); // TODO: expectedType = definedParameterType
Expand Down Expand Up @@ -590,12 +606,12 @@ Stack<ParameterCleanupItem> GenerateCodeForParameterPassing(OperatorCall functio
if (StatementCanBeDeallocated(passedParameter, out bool explicitDeallocate))
{
if (explicitDeallocate && !canDeallocate)
{ Warnings.Add(new Warning($"Can not deallocate this value: parameter definition does not have a \"{"temp"}\" modifier", passedParameter, CurrentFile)); }
{ AnalysisCollection?.Warnings.Add(new Warning($"Can not deallocate this value: parameter definition does not have a \"{"temp"}\" modifier", passedParameter, CurrentFile)); }
}
else
{
if (explicitDeallocate)
{ Warnings.Add(new Warning($"Can not deallocate this value", passedParameter, CurrentFile)); }
{ AnalysisCollection?.Warnings.Add(new Warning($"Can not deallocate this value", passedParameter, CurrentFile)); }
canDeallocate = false;
}

Expand Down Expand Up @@ -627,7 +643,7 @@ void GenerateCodeForFunctionCall_Function(FunctionCall functionCall, CompiledFun
{
if (!compiledFunction.CanUse(CurrentFile))
{
Errors.Add(new Error($"The {compiledFunction.ToReadable()} function could not be called due to its protection level", functionCall.Identifier, CurrentFile));
AnalysisCollection?.Errors.Add(new Error($"The {compiledFunction.ToReadable()} function could not be called due to its protection level", functionCall.Identifier, CurrentFile));
return;
}

Expand All @@ -651,10 +667,10 @@ void GenerateCodeForFunctionCall_Function(FunctionCall functionCall, CompiledFun

Builder.CodeBuilder.AppendInstruction(ASM.Instruction.LEA, Registers.EBX, (InstructionOperand)new ValueAddress(0, AddressingMode.BasePointerRelative));

Builder.CodeBuilder.Call_stdcall("_WriteFile@20", 20,
Builder.CodeBuilder.Call_stdcall("_WriteFile@20", 20,
Registers.EAX,
dataLabel,
charLiteral.Value.Length,
dataLabel,
charLiteral.Value.Length,
Registers.EBX,
0);
return;
Expand Down Expand Up @@ -706,7 +722,7 @@ void GenerateCodeForFunctionCall_Function(FunctionCall functionCall, CompiledFun
}

if (compiledFunction.IsMacro)
{ Warnings.Add(new Warning($"I can not inline macros because of lack of intelligence so I will treat this macro as a normal function.", functionCall, CurrentFile)); }
{ AnalysisCollection?.Warnings.Add(new Warning($"I can not inline macros because of lack of intelligence so I will treat this macro as a normal function.", functionCall, CurrentFile)); }

Stack<ParameterCleanupItem> parameterCleanup;

Expand Down Expand Up @@ -1151,7 +1167,7 @@ void GenerateCodeForStatement(ConstructorCall constructorCall)

if (!constructor.CanUse(CurrentFile))
{
Errors.Add(new Error($"The \"{constructorCall.TypeName}\" constructor cannot be called due to its protection level", constructorCall.Keyword, CurrentFile));
AnalysisCollection?.Errors.Add(new Error($"The \"{constructorCall.TypeName}\" constructor cannot be called due to its protection level", constructorCall.Keyword, CurrentFile));
return;
}

Expand Down Expand Up @@ -1521,7 +1537,7 @@ void GenerateCodeForStatement(Field field)
}
void GenerateCodeForStatement(TypeCast typeCast)
{
Warnings.Add(new Warning($"Type-cast is not supported. I will ignore it and compile just the value", new Position(typeCast.Keyword, typeCast.Type), CurrentFile));
AnalysisCollection?.Warnings.Add(new Warning($"Type-cast is not supported. I will ignore it and compile just the value", new Position(typeCast.Keyword, typeCast.Type), CurrentFile));

GenerateCodeForStatement(typeCast.PrevStatement);
}
Expand Down Expand Up @@ -1620,15 +1636,13 @@ void GenerateCodeForTopLevelStatements(Statement[] statements)

void CompileParameters(ParameterDefinition[] parameters)
{
int paramIndex = 0;
int paramsSize = 0;
for (int i = 0; i < parameters.Length; i++)
{
paramIndex++;
CompiledType parameterType = new(parameters[i].Type, FindType);
parameters[i].Type.SetAnalyzedType(parameterType);

this.CompiledParameters.Add(new CompiledParameter(paramIndex, paramsSize, parameterType, parameters[i]));
this.CompiledParameters.Add(new CompiledParameter(i, -(paramsSize + 1 + CodeGeneratorForMain.TagsBeforeBasePointer), parameterType, parameters[i]));

paramsSize += parameterType.SizeOnStack;
}
Expand Down Expand Up @@ -1743,13 +1757,10 @@ AsmGeneratorResult GenerateCode(CompilerResult compilerResult, PrintCallback? pr
"_ExitProcess@4",
},
}),

Warnings = Warnings.ToArray(),
Errors = Errors.ToArray(),
};
}

public static AsmGeneratorResult Generate(CompilerResult compilerResult, AsmGeneratorSettings generatorSettings, PrintCallback? printCallback = null)
=> new CodeGeneratorForAsm(compilerResult, generatorSettings).GenerateCode(compilerResult, printCallback);
public static AsmGeneratorResult Generate(CompilerResult compilerResult, AsmGeneratorSettings generatorSettings, PrintCallback? printCallback = null, AnalysisCollection? analysisCollection = null)
=> new CodeGeneratorForAsm(compilerResult, generatorSettings, analysisCollection).GenerateCode(compilerResult, printCallback);
}
}
36 changes: 36 additions & 0 deletions Source/ASM/Core.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using System;

namespace LanguageCore.ASM
{
public class ProcessException : Exception
{
readonly string processName;
readonly int exitCode;
readonly string stdOutput;
readonly string stdError;

public override string Message => $"Process \"{processName}\" exited with code {exitCode}";
public string StandardOutput => stdOutput;
public string StandardError => stdError;

public ProcessException(string processName, int exitCode, string stdOutput, string stdError) : base()
{
this.processName = processName;
this.exitCode = exitCode;
this.stdOutput = stdOutput;
this.stdError = stdError;
}
}

public class ProcessNotStartedException : Exception
{
readonly string processName;

public override string Message => $"Failed to start process \"{processName}\"";

public ProcessNotStartedException(string processName) : base()
{
this.processName = processName;
}
}
}
Loading

0 comments on commit c928a01

Please sign in to comment.