Format with clang

This commit is contained in:
2021-11-09 19:41:10 +01:00
parent ee016636f7
commit 61906b3c80
38 changed files with 2277 additions and 2364 deletions

107
.clang-format Normal file
View File

@@ -0,0 +1,107 @@
---
Language: Cpp
DisableFormat: false
Standard: Latest
BasedOnStyle: WebKit
TabWidth: 4
IndentWidth: 4
ContinuationIndentWidth: 4
ConstructorInitializerIndentWidth: 1
UseTab: Never
ColumnLimit: 120
AccessModifierOffset: -4
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: false
AlignEscapedNewlines: DontAlign
AlignOperands: false
AlignTrailingComments: false
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortLambdasOnASingleLine: Inline
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: No
BinPackArguments: false
BinPackParameters: false
# Configure each individual brace in BraceWrapping
BreakBeforeBraces: Custom
# Control of individual brace wrapping cases
BraceWrapping:
AfterCaseLabel: true
AfterClass: false
AfterControlStatement: Always
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterUnion: true
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: true
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: true
BreakAfterJavaFieldAnnotations: true
BreakBeforeTernaryOperators: false
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: false
CommentPragmas: "^ IWYU pragma:"
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
Cpp11BracedListStyle: true
FixNamespaceComments: false
IndentCaseLabels: true
IndentPPDirectives: BeforeHash
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ""
MacroBlockEnd: ""
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Middle
# QualifierAlignment: Right # Only supported in clang-format 14+
# ReferenceAlignmentStyle: Middle # Only supported in clang-format 14+
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: Never
SpaceBeforeRangeBasedForLoopColon: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
# Comments are for developers, they should arrange them
ReflowComments: false
IncludeBlocks: Preserve
---

9
bin/fibonacci.wasm Normal file
View File

@@ -0,0 +1,9 @@
# Get a number from STDIN
# Clobbers registers
get_user_integer:
seti [STRING_STORAGE]
seti %A $0;
seti %B $100;
int $5;

5
compile_flags.txt Normal file
View File

@@ -0,0 +1,5 @@
-xc++
-Wall
-Wextra
-Iinclude/
-std=c++17

View File

@@ -2,24 +2,19 @@
#include <string>
#include <token/token.hpp>
#include <unordered_map>
#include <vector>
#include <utility>
#include <vector>
namespace Compile
{
class Compiler
{
class Compiler {
private:
std::unordered_map<std::string, std::size_t> jumpLabelLocations;
std::vector<std::pair<Token::Token, std::size_t>> unresolvedJumpLabels;
void InsertAsBytes(
Token::Token const & token,
std::vector<std::uint8_t> & bytes);
void InsertAsBytes(Token::Token const & token, std::vector<std::uint8_t> & bytes);
public:
bool Compile(
std::vector<Token::Token> const & tokens,
std::vector<std::uint8_t> & bytes);
bool Compile(std::vector<Token::Token> const & tokens, std::vector<std::uint8_t> & bytes);
};
}

View File

@@ -4,8 +4,7 @@
namespace Compile
{
class CompilationError
{
class CompilationError {
public:
Token::Token errorToken;

View File

@@ -1,9 +1,9 @@
#pragma once
#include <variant>
#include <execute/bytecode.hpp>
#include <execute/error.hpp>
#include <execute/state.hpp>
#include <stdexcept>
#include <variant>
#include <vector>
namespace Execute
@@ -15,8 +15,7 @@ namespace Execute
Memory
};
class ArgumentValue
{
class ArgumentValue {
private:
ArgumentType type;
ArgumentType memoryValueType;
@@ -30,8 +29,6 @@ namespace Execute
int Read(State & state) const;
// Returns the size of the argument in bytes
std::size_t Parse(
std::vector<std::uint8_t> const & memory,
std::size_t const pos);
std::size_t Parse(std::vector<std::uint8_t> const & memory, std::size_t const pos);
};
}

View File

@@ -3,8 +3,7 @@
namespace Execute
{
class RuntimeError
{
class RuntimeError {
protected:
std::string message;
std::size_t byteLocation;
@@ -16,35 +15,28 @@ namespace Execute
RuntimeError(std::string const & what, std::size_t const byteLocation);
};
class InterruptIndexOutOfRange : public RuntimeError
{
class InterruptIndexOutOfRange : public RuntimeError {
public:
InterruptIndexOutOfRange(std::size_t const location, int const index);
};
class AttemptedWriteToImmediate : public RuntimeError
{
class AttemptedWriteToImmediate : public RuntimeError {
public:
AttemptedWriteToImmediate(std::size_t const location);
};
class NonExecutableInstruction : public RuntimeError
{
class NonExecutableInstruction : public RuntimeError {
public:
NonExecutableInstruction(std::size_t const location);
};
class NonArgumentByte : public RuntimeError
{
class NonArgumentByte : public RuntimeError {
public:
NonArgumentByte(std::size_t const location);
};
class OutOfMemory : public RuntimeError
{
class OutOfMemory : public RuntimeError {
public:
OutOfMemory(
std::size_t const requiredMemorySize,
std::size_t const actualMemorySize);
OutOfMemory(std::size_t const requiredMemorySize, std::size_t const actualMemorySize);
};
}

View File

@@ -5,8 +5,5 @@
namespace Execute
{
void ExecuteInterrupt(
int const id,
Execute::Registers & registers,
std::vector<std::uint8_t> & memory);
void ExecuteInterrupt(int const id, Execute::Registers & registers, std::vector<std::uint8_t> & memory);
}

View File

@@ -6,20 +6,15 @@
namespace Execute
{
class VirtualMachine
{
class VirtualMachine {
private:
State state;
void DoArithmatic(
InstructionByte const instruction,
std::array<ArgumentValue, 3> & arguments);
void DoArithmatic(InstructionByte const instruction, std::array<ArgumentValue, 3> & arguments);
void SetInteger(std::array<ArgumentValue, 3> & arguments);
void ExecuteJump(std::array<ArgumentValue, 3> & arguments);
void ExecuteInterrupt(std::array<ArgumentValue, 3> & arguments);
void ExecuteCall(
std::array<ArgumentValue, 3> & arguments,
std::size_t const returnByte);
void ExecuteCall(std::array<ArgumentValue, 3> & arguments, std::size_t const returnByte);
void ExecuteReturn();
void DoBooleanLogic(
InstructionByte const instruction,
@@ -35,9 +30,7 @@ namespace Execute
void SingleStep();
void SetMemorySize(std::size_t const size);
void LoadCode(
std::vector<std::uint8_t> const & byteCode,
bool const printDecodedBytes);
void LoadCode(std::vector<std::uint8_t> const & byteCode, bool const printDecodedBytes);
State const & GetState() const;
Execute::InstructionByte GetCurrentInstruction() const;

View File

@@ -2,15 +2,12 @@
#include <string>
#include <vector>
class Preprocessor
{
class Preprocessor {
private:
std::vector<std::string> substitutionIdentifiers;
std::vector<std::string> substitutionValues;
void extractComment(std::string & line,
std::size_t const lineNumber,
std::size_t const lineColumn);
void extractComment(std::string & line, std::size_t const lineNumber, std::size_t const lineColumn);
void processLine(std::string & line, std::size_t const lineNumber);

View File

@@ -22,8 +22,18 @@ namespace Token
Token(TokenType type, bool validness, int const lineNumber, int const lineColumn);
Token(TokenType type, std::string const & string, bool validness, int const lineNumber, int const lineColumn);
Token(TokenType type, int value, bool validness, int const lineNumber, int const lineColumn);
Token(TokenType type, RegisterType const registerType, bool validness, int const lineNumber, int const lineColumn);
Token(TokenType type, OperandType const OperandType, bool validness, int const lineNumber, int const lineColumn);
Token(
TokenType type,
RegisterType const registerType,
bool validness,
int const lineNumber,
int const lineColumn);
Token(
TokenType type,
OperandType const OperandType,
bool validness,
int const lineNumber,
int const lineColumn);
public:
int const lineNumber;
@@ -37,7 +47,8 @@ namespace Token
Token(Token const & other);
static Token CreateEmptyToken(int const lineNumber, int const lineColumn);
static Token CreateErrorToken(std::string const & message, TokenType const type, int const lineNumber, int const lineColumn);
static Token
CreateErrorToken(std::string const & message, TokenType const type, int const lineNumber, int const lineColumn);
static Token CreateStatementEndToken(int const lineNumber, int const lineColumn);
static Token CreateLabelDefinitionToken(std::string const & string, int const lineNumber, int const lineColumn);
static Token CreateLabelArgumentToken(std::string const & string, int const lineNumber, int const lineColumn);

View File

@@ -5,19 +5,13 @@
namespace Token
{
class Tokenizer
{
class Tokenizer {
private:
// Argument for string should never be of length zero
Token ExtractToken(
std::string const & string,
std::size_t const lineNumber,
std::size_t const lineColumn) const;
Token
ExtractToken(std::string const & string, std::size_t const lineNumber, std::size_t const lineColumn) const;
public:
void Tokenize(
std::string const & line,
std::size_t const lineNumber,
std::vector<Token> & tokens);
void Tokenize(std::string const & line, std::size_t const lineNumber, std::vector<Token> & tokens);
};
}

View File

@@ -9,21 +9,14 @@ namespace Utils
bool isWhitespaceCharacter(char const c);
// Returns nullopt in case the value is missing its terminator character
std::optional<std::string> getValueSurroundedBy(
std::string const & src,
std::size_t const pos,
char const surroundingCharacter);
std::optional<std::string>
getValueSurroundedBy(std::string const & src, std::size_t const pos, char const surroundingCharacter);
std::string getValueSurroundedByWhitespace(
std::string const & src,
std::size_t const pos);
std::string getValueSurroundedByWhitespace(std::string const & src, std::size_t const pos);
namespace Bytes
{
void Write(
int const value,
std::vector<std::uint8_t> & vec,
std::size_t const pos);
void Write(int const value, std::vector<std::uint8_t> & vec, std::size_t const pos);
int Read(std::vector<std::uint8_t> const & vec, std::size_t const pos);
}

View File

@@ -3,30 +3,23 @@
#include <execute/virtualmachine.hpp>
#include <token/tokenizer.hpp>
class Wassembler
{
class Wassembler {
private:
Execute::VirtualMachine vm;
bool printSubstitutions;
bool printTokens;
bool printTranslatedBytes;
bool LoadTextFile(
std::string const & filePath,
std::vector<std::string> & lines) const;
bool LoadTextFile(std::string const & filePath, std::vector<std::string> & lines) const;
bool Preprocess(std::vector<std::string> & lines) const;
bool Tokenize(
std::vector<std::string> const & lines,
std::vector<Token::Token> & tokens) const;
bool Tokenize(std::vector<std::string> const & lines, std::vector<Token::Token> & tokens) const;
bool CompileToBytes(
std::vector<Token::Token> const & tokens,
std::vector<std::string> const & lines,
std::vector<std::uint8_t> & bytes) const;
void ExecuteCode(std::vector<std::uint8_t> const & bytes);
bool CompileFile(
std::string const & filePath,
std::vector<std::uint8_t> & bytes) const;
bool CompileFile(std::string const & filePath, std::vector<std::uint8_t> & bytes) const;
public:
void SetMemorySize(unsigned const size);
@@ -36,9 +29,7 @@ public:
void EnableByteTranslationLogging();
bool CompileAndRun(std::string const & filePath);
bool CompileToFile(
std::string const & inputFilePath,
std::string const & outputFilePath);
bool CompileToFile(std::string const & inputFilePath, std::string const & outputFilePath);
Wassembler() = default;
};

View File

@@ -1,6 +1,6 @@
CC = g++
CFLAGS = -g -std=c++17 -Wall -Iinclude #-Werror
LFLAGS = #-lsfml-graphics -lsfml-window -lsfml-system
CFLAGS = -g -std=c++17 -Wall -Wextra -Iinclude
LFLAGS =
CPPS = $(shell find src/ -name '*.cpp')
OBJS = $(patsubst src/%.cpp, build/%.o, ${CPPS})

View File

@@ -8,7 +8,7 @@ namespace Compile
{
int GetRequiredNumberOfArguments(Token::OperandType const type)
{
switch (type)
switch(type)
{
case Token::OperandType::AddInteger:
case Token::OperandType::SubtractInteger:
@@ -32,7 +32,9 @@ namespace Compile
return 1;
default:
std::printf("WARNING: returning default argument length of 0 for operand type %i\n", static_cast<int>(type));
std::printf(
"WARNING: returning default argument length of 0 for operand type %i\n",
static_cast<int>(type));
case Token::OperandType::ReturnFromFunction:
case Token::OperandType::ExitProgram:
return 0;
@@ -41,31 +43,22 @@ namespace Compile
bool IsArgumentToken(Token::Token const & t)
{
return
t.type == Token::TokenType::ImmediateInteger ||
t.type == Token::TokenType::Register ||
t.type == Token::TokenType::LabelArgument ||
t.type == Token::TokenType::Memory;
return t.type == Token::TokenType::ImmediateInteger || t.type == Token::TokenType::Register
|| t.type == Token::TokenType::LabelArgument || t.type == Token::TokenType::Memory;
}
bool IsReadableToken(Token::Token const & t)
{
return
t.type == Token::TokenType::ImmediateInteger ||
t.type == Token::TokenType::Register ||
t.type == Token::TokenType::Memory;
return t.type == Token::TokenType::ImmediateInteger || t.type == Token::TokenType::Register
|| t.type == Token::TokenType::Memory;
}
bool IsWriteableToken(Token::Token const & t)
{
return
t.type == Token::TokenType::Register ||
t.type == Token::TokenType::Memory;
return t.type == Token::TokenType::Register || t.type == Token::TokenType::Memory;
}
void ValidateArguments(
std::vector<Token::Token> const & tokens,
std::size_t const operandIndex)
void ValidateArguments(std::vector<Token::Token> const & tokens, std::size_t const operandIndex)
{
auto const operandType = std::get<Token::OperandType>(tokens[operandIndex].data);
switch(operandType)
@@ -77,15 +70,15 @@ namespace Compile
case Token::OperandType::MultiplyInteger:
case Token::OperandType::ShiftIntegerLeft:
case Token::OperandType::ShiftIntegerRight:
if (!IsReadableToken(tokens[operandIndex + 1]))
if(!IsReadableToken(tokens[operandIndex + 1]))
{
throw CompilationError::CreateExpectedImmediateOrRegisterOrMemory(tokens[operandIndex + 1]);
}
if (!IsReadableToken(tokens[operandIndex + 2]))
if(!IsReadableToken(tokens[operandIndex + 2]))
{
throw CompilationError::CreateExpectedImmediateOrRegisterOrMemory(tokens[operandIndex + 2]);
}
if (!IsWriteableToken(tokens[operandIndex + 3]))
if(!IsWriteableToken(tokens[operandIndex + 3]))
{
throw CompilationError::CreateExpectedRegisterOrMemoryError(tokens[operandIndex + 3]);
}
@@ -96,11 +89,11 @@ namespace Compile
case Token::OperandType::GreaterThanInteger:
case Token::OperandType::EqualInteger:
case Token::OperandType::SetInteger:
if (!IsReadableToken(tokens[operandIndex + 1]))
if(!IsReadableToken(tokens[operandIndex + 1]))
{
throw CompilationError::CreateExpectedImmediateOrRegisterOrMemory(tokens[operandIndex + 1]);
}
if (!IsReadableToken(tokens[operandIndex + 2]))
if(!IsReadableToken(tokens[operandIndex + 2]))
{
throw CompilationError::CreateExpectedImmediateOrRegisterOrMemory(tokens[operandIndex + 2]);
}
@@ -109,7 +102,7 @@ namespace Compile
// 1 Label value
case Token::OperandType::Jump:
case Token::OperandType::CallFunction:
if (tokens[operandIndex + 1].type != Token::TokenType::LabelArgument)
if(tokens[operandIndex + 1].type != Token::TokenType::LabelArgument)
{
throw CompilationError::CreateExpectedLabelError(tokens[operandIndex + 1]);
}
@@ -118,7 +111,7 @@ namespace Compile
// 1 Read value
case Token::OperandType::Interrupt:
case Token::OperandType::PushInteger:
if (!IsReadableToken(tokens[operandIndex + 1]))
if(!IsReadableToken(tokens[operandIndex + 1]))
{
throw CompilationError::CreateExpectedImmediateOrRegisterOrMemory(tokens[operandIndex + 1]);
}
@@ -126,7 +119,7 @@ namespace Compile
// 1 Write value
case Token::OperandType::PopInteger:
if (!IsWriteableToken(tokens[operandIndex + 1]))
if(!IsWriteableToken(tokens[operandIndex + 1]))
{
throw CompilationError::CreateExpectedRegisterOrMemoryError(tokens[operandIndex + 1]);
}
@@ -158,9 +151,7 @@ namespace Compile
}
}
void Compiler::InsertAsBytes(
Token::Token const & token,
std::vector<std::uint8_t> & bytes)
void Compiler::InsertAsBytes(Token::Token const & token, std::vector<std::uint8_t> & bytes)
{
switch(token.type)
{
@@ -256,7 +247,8 @@ namespace Compile
case Token::TokenType::Register:
bytes.push_back(static_cast<std::uint8_t>(Execute::InstructionByte::REGISTER));
bytes.push_back(static_cast<std::uint8_t>(GetByteCodeRegister(std::get<Token::RegisterType>(token.data))));
bytes.push_back(
static_cast<std::uint8_t>(GetByteCodeRegister(std::get<Token::RegisterType>(token.data))));
break;
case Token::TokenType::StatementEnd:
@@ -270,7 +262,7 @@ namespace Compile
auto const & label = std::get<std::string>(token.data);
auto const findResult = jumpLabelLocations.find(label);
int jumpLocation = 0;
if (findResult == jumpLabelLocations.end())
if(findResult == jumpLabelLocations.end())
{
unresolvedJumpLabels.push_back(std::make_pair(token, bytes.size()));
}
@@ -292,7 +284,8 @@ namespace Compile
{
case Token::TokenValueType::Register:
bytes.push_back(static_cast<std::uint8_t>(Execute::InstructionByte::REGISTER));
bytes.push_back(static_cast<std::uint8_t>(GetByteCodeRegister(std::get<Token::RegisterType>(token.data))));
bytes.push_back(
static_cast<std::uint8_t>(GetByteCodeRegister(std::get<Token::RegisterType>(token.data))));
break;
case Token::TokenValueType::Integer:
@@ -315,9 +308,7 @@ namespace Compile
}
}
bool Compiler::Compile(
std::vector<Token::Token> const & tokens,
std::vector<std::uint8_t> & bytes)
bool Compiler::Compile(std::vector<Token::Token> const & tokens, std::vector<std::uint8_t> & bytes)
{
jumpLabelLocations.clear();
unresolvedJumpLabels.clear();
@@ -348,7 +339,7 @@ namespace Compile
operandType = std::get<Token::OperandType>(token.data);
expectedNumberOfArguments = GetRequiredNumberOfArguments(operandType);
if (expectedNumberOfArguments < 1)
if(expectedNumberOfArguments < 1)
{
state = State::FindStatementEnd;
}
@@ -361,7 +352,7 @@ namespace Compile
case Token::TokenType::LabelDefinition:
{
auto findResult = jumpLabelLocations.find(std::get<std::string>(token.data));
if (findResult == jumpLabelLocations.end())
if(findResult == jumpLabelLocations.end())
{
jumpLabelLocations[std::get<std::string>(token.data)] = bytes.size();
}
@@ -382,10 +373,10 @@ namespace Compile
break;
case State::FindArguments:
if (IsArgumentToken(token))
if(IsArgumentToken(token))
{
expectedNumberOfArguments -= 1;
if (expectedNumberOfArguments < 1)
if(expectedNumberOfArguments < 1)
{
ValidateArguments(tokens, operatorTokenIndex);
state = State::FindStatementEnd;
@@ -399,26 +390,24 @@ namespace Compile
break;
case State::FindStatementEnd:
if (token.type != Token::TokenType::StatementEnd)
if(token.type != Token::TokenType::StatementEnd)
{
// TODO Further specify this error?
throw CompilationError::CreateExpectedEndOfStatementError(token);
}
else
{
InsertAsBytes(
token,
bytes);
InsertAsBytes(token, bytes);
state = State::FindOperand;
}
break;
}
}
for(auto const & unresolved : unresolvedJumpLabels)
for(auto const & unresolved: unresolvedJumpLabels)
{
auto const & findResult = jumpLabelLocations.find(std::get<std::string>(unresolved.first.data));
if (findResult == jumpLabelLocations.end())
if(findResult == jumpLabelLocations.end())
{
throw CompilationError::CreateNonExistingLabelError(unresolved.first);
}

View File

@@ -3,10 +3,7 @@
namespace Compile
{
CompilationError::CompilationError(
std::string const & message,
Token::Token const & token)
: errorToken(token)
CompilationError::CompilationError(std::string const & message, Token::Token const & token) : errorToken(token)
{
errorToken.errorMessage = message;
}

View File

@@ -26,7 +26,7 @@ namespace Execute
std::uint8_t * ArgumentValue::GetMemory(State & state) const
{
switch (memoryValueType)
switch(memoryValueType)
{
case ArgumentType::Immediate:
return &(state.memory[std::get<int>(data)]);
@@ -41,7 +41,7 @@ namespace Execute
void ArgumentValue::Write(int const value, State & state) const
{
if (type == ArgumentType::Immediate)
if(type == ArgumentType::Immediate)
{
throw AttemptedWriteToImmediate(state.registers.programCounter);
}
@@ -94,9 +94,7 @@ namespace Execute
}
// Returns the size of the argument in bytes
std::size_t ArgumentValue::Parse(
std::vector<std::uint8_t> const & memory,
std::size_t const pos)
std::size_t ArgumentValue::Parse(std::vector<std::uint8_t> const & memory, std::size_t const pos)
{
InstructionByte const valueByte = static_cast<InstructionByte>(memory[pos]);
switch(valueByte)

View File

@@ -2,23 +2,13 @@
namespace Execute
{
std::string const & RuntimeError::GetMessage() const
{
return message;
}
std::string const & RuntimeError::GetMessage() const { return message; }
RuntimeError::RuntimeError()
: message("Undocumented runtime error")
{
}
RuntimeError::RuntimeError() : message("Undocumented runtime error") { }
RuntimeError::RuntimeError(
std::string const & what,
std::size_t const _byteLocation)
: message(what),
byteLocation(_byteLocation)
{
}
RuntimeError::RuntimeError(std::string const & what, std::size_t const _byteLocation)
: message(what), byteLocation(_byteLocation)
{ }
InterruptIndexOutOfRange::InterruptIndexOutOfRange(std::size_t const location, int const index)
: RuntimeError("", location)
@@ -30,32 +20,27 @@ namespace Execute
message += " is out of range";
}
AttemptedWriteToImmediate::AttemptedWriteToImmediate(std::size_t const location)
: RuntimeError("", location)
AttemptedWriteToImmediate::AttemptedWriteToImmediate(std::size_t const location) : RuntimeError("", location)
{
message = "Instruction at ";
message += std::to_string(location);
message += " attempted to write to an immediate value";
}
NonExecutableInstruction::NonExecutableInstruction(std::size_t const location)
: RuntimeError("", location)
NonExecutableInstruction::NonExecutableInstruction(std::size_t const location) : RuntimeError("", location)
{
message = "Attempted to execute byte at ";
message += std::to_string(location);
message += " which is not an instruction byte";
}
NonArgumentByte::NonArgumentByte(std::size_t const location)
: RuntimeError("", location)
NonArgumentByte::NonArgumentByte(std::size_t const location) : RuntimeError("", location)
{
message = "Expected an argument byte (immediate, register or memory location) at ";
message += std::to_string(location);
}
OutOfMemory::OutOfMemory(
std::size_t const requiredMemorySize,
std::size_t const actualMemorySize)
OutOfMemory::OutOfMemory(std::size_t const requiredMemorySize, std::size_t const actualMemorySize)
{
message = "Not enough memory to fit code. Actual size is ";
message += std::to_string(actualMemorySize);

View File

@@ -5,10 +5,7 @@
namespace Execute
{
void ExecuteInterrupt(
int const id,
Execute::Registers & registers,
std::vector<std::uint8_t> & memory)
void ExecuteInterrupt(int const id, Execute::Registers & registers, std::vector<std::uint8_t> & memory)
{
switch(id)
{
@@ -40,24 +37,25 @@ namespace Execute
case 10:
{
registers.A = std::getchar();
if (registers.A == '\n')
if(registers.A == '\n')
{
return;
}
while(std::getchar() != '\n');
while(std::getchar() != '\n')
;
}
break;
case 11:
{
if (registers.B <= 0)
if(registers.B <= 0)
{
registers.B = 0;
return;
}
if (registers.A < 0 || static_cast<unsigned>(registers.A + registers.B) >= memory.size())
if(registers.A < 0 || static_cast<unsigned>(registers.A + registers.B) >= memory.size())
{
throw OutOfMemory(registers.A, registers.B);
}
@@ -67,7 +65,7 @@ namespace Execute
while(charactersRead < registers.B)
{
char result = std::getchar();
if (result == '\n')
if(result == '\n')
{
newlineRead = true;
break;
@@ -79,9 +77,10 @@ namespace Execute
registers.B = charactersRead;
if (!newlineRead)
if(!newlineRead)
{
while(std::getchar() != '\n');
while(std::getchar() != '\n')
;
}
}
break;

View File

@@ -53,11 +53,9 @@ namespace Execute
return memoryOffset - memoryPos;
}
void VirtualMachine::DoArithmatic(
InstructionByte const instruction,
std::array<ArgumentValue, 3> & arguments)
void VirtualMachine::DoArithmatic(InstructionByte const instruction, std::array<ArgumentValue, 3> & arguments)
{
switch (instruction)
switch(instruction)
{
case InstructionByte::ADD_INTEGER:
arguments[2].Write(arguments[0].Read(state) + arguments[1].Read(state), state);
@@ -104,9 +102,7 @@ namespace Execute
Execute::ExecuteInterrupt(interruptNo, state.registers, state.memory);
}
void VirtualMachine::ExecuteCall(
std::array<ArgumentValue, 3> & arguments,
std::size_t const returnByte)
void VirtualMachine::ExecuteCall(std::array<ArgumentValue, 3> & arguments, std::size_t const returnByte)
{
state.PushToStack(returnByte);
state.registers.programCounter = arguments[0].Read(state);
@@ -142,7 +138,7 @@ namespace Execute
throw std::runtime_error("Unhandled instruction byte for boolean logic");
}
if (executeNextInstruction)
if(executeNextInstruction)
{
state.registers.programCounter = nextInstruction;
return;
@@ -171,8 +167,7 @@ namespace Execute
// Default to 1 byte (= 1 instruction)
std::size_t programCounterIncrement = 1;
std::array<ArgumentValue, 3> arguments;
InstructionByte const instruction =
static_cast<InstructionByte>(state.memory[state.registers.programCounter]);
InstructionByte const instruction = static_cast<InstructionByte>(state.memory[state.registers.programCounter]);
switch(instruction)
{
case InstructionByte::ADD_INTEGER:
@@ -181,50 +176,34 @@ namespace Execute
case InstructionByte::MULTIPLY_INTEGER:
case InstructionByte::SHIFT_LEFT_INTEGER:
case InstructionByte::SHIFT_RIGHT_INTEGER:
programCounterIncrement += GetArguments(
instruction,
arguments,
state.memory,
state.registers.programCounter + 1);
programCounterIncrement
+= GetArguments(instruction, arguments, state.memory, state.registers.programCounter + 1);
DoArithmatic(instruction, arguments);
state.registers.programCounter += programCounterIncrement;
break;
case InstructionByte::SET_INTEGER:
programCounterIncrement += GetArguments(
instruction,
arguments,
state.memory,
state.registers.programCounter + 1);
programCounterIncrement
+= GetArguments(instruction, arguments, state.memory, state.registers.programCounter + 1);
SetInteger(arguments);
state.registers.programCounter += programCounterIncrement;
break;
case InstructionByte::JUMP:
GetArguments(
instruction,
arguments,
state.memory,
state.registers.programCounter + 1);
GetArguments(instruction, arguments, state.memory, state.registers.programCounter + 1);
ExecuteJump(arguments);
break;
case InstructionByte::INTERRUPT:
programCounterIncrement += GetArguments(
instruction,
arguments,
state.memory,
state.registers.programCounter + 1);
programCounterIncrement
+= GetArguments(instruction, arguments, state.memory, state.registers.programCounter + 1);
ExecuteInterrupt(arguments);
state.registers.programCounter += programCounterIncrement;
break;
case InstructionByte::CALL:
programCounterIncrement += GetArguments(
instruction,
arguments,
state.memory,
state.registers.programCounter + 1);
programCounterIncrement
+= GetArguments(instruction, arguments, state.memory, state.registers.programCounter + 1);
ExecuteCall(arguments, state.registers.programCounter + programCounterIncrement);
break;
@@ -239,33 +218,21 @@ namespace Execute
case InstructionByte::LESS_THAN_INTEGER:
case InstructionByte::GREATER_THAN_INTEGER:
case InstructionByte::EQUALS_INTEGER:
programCounterIncrement += GetArguments(
instruction,
arguments,
state.memory,
state.registers.programCounter + 1);
DoBooleanLogic(
instruction,
arguments,
state.registers.programCounter + programCounterIncrement);
programCounterIncrement
+= GetArguments(instruction, arguments, state.memory, state.registers.programCounter + 1);
DoBooleanLogic(instruction, arguments, state.registers.programCounter + programCounterIncrement);
break;
case InstructionByte::POP_INTEGER:
programCounterIncrement += GetArguments(
instruction,
arguments,
state.memory,
state.registers.programCounter + 1);
programCounterIncrement
+= GetArguments(instruction, arguments, state.memory, state.registers.programCounter + 1);
ExecutePop(arguments);
state.registers.programCounter += programCounterIncrement;
break;
case InstructionByte::PUSH_INTEGER:
programCounterIncrement += GetArguments(
instruction,
arguments,
state.memory,
state.registers.programCounter + 1);
programCounterIncrement
+= GetArguments(instruction, arguments, state.memory, state.registers.programCounter + 1);
ExecutePush(arguments);
state.registers.programCounter += programCounterIncrement;
break;
@@ -410,26 +377,21 @@ namespace Execute
}
}
void VirtualMachine::SetMemorySize(std::size_t const size)
{
state.memory.resize(size);
}
void VirtualMachine::SetMemorySize(std::size_t const size) { state.memory.resize(size); }
void VirtualMachine::LoadCode(
std::vector<std::uint8_t> const & byteCode,
bool const printDecodedBytes)
void VirtualMachine::LoadCode(std::vector<std::uint8_t> const & byteCode, bool const printDecodedBytes)
{
if (printDecodedBytes)
if(printDecodedBytes)
{
PrintBytes(byteCode);
}
if (state.memory.size() < byteCode.size())
if(state.memory.size() < byteCode.size())
{
throw OutOfMemory(byteCode.size(), state.memory.size());
}
for (std::size_t i = 0; i < byteCode.size(); ++i)
for(std::size_t i = 0; i < byteCode.size(); ++i)
{
state.memory[i] = byteCode[i];
}

View File

@@ -11,22 +11,17 @@ int main(int argc, char ** argv)
bool execute = false, compile = false;
std::string outputFile("program.bin");
auto cli = (
clipp::value("input file (*.wasm or *.bin)").set(inputFile),
(
clipp::required("-e", "--execute").set(execute),
auto cli
= (clipp::value("input file (*.wasm or *.bin)").set(inputFile),
(clipp::required("-e", "--execute").set(execute),
clipp::option("-m", "--memory-size") & clipp::value("memory size in bytes (defaults to 4096)", memorySize),
clipp::option("-pb", "--print-bytes").set(printBytes)
) |
(
clipp::required("-c", "--compile").set(compile),
clipp::option("-o", "--output-file") & clipp::value("output file", outputFile)
),
clipp::option("-pb", "--print-bytes").set(printBytes))
| (clipp::required("-c", "--compile").set(compile),
clipp::option("-o", "--output-file") & clipp::value("output file", outputFile)),
clipp::option("-ps", "--print-substitutions").set(printSubstitutions),
clipp::option("-pt", "--print-tokens").set(printTokens)
);
clipp::option("-pt", "--print-tokens").set(printTokens));
if (!clipp::parse(argc, argv, cli))
if(!clipp::parse(argc, argv, cli))
{
std::cout << clipp::make_man_page(cli, argv[0]);
return 1;
@@ -34,32 +29,32 @@ int main(int argc, char ** argv)
Wassembler wassembler;
wassembler.SetMemorySize(memorySize);
if (printSubstitutions)
if(printSubstitutions)
{
wassembler.EnableSubstitutionsLogging();
}
if (printTokens)
if(printTokens)
{
wassembler.EnableTokensLogging();
}
if (execute)
if(execute)
{
if (printBytes)
if(printBytes)
{
wassembler.EnableByteTranslationLogging();
}
if (!wassembler.CompileAndRun(inputFile))
if(!wassembler.CompileAndRun(inputFile))
{
exit(1);
}
}
if (compile)
if(compile)
{
if (!wassembler.CompileToFile(inputFile, outputFile))
if(!wassembler.CompileToFile(inputFile, outputFile))
{
exit(1);
}

View File

@@ -9,14 +9,14 @@ bool trySubstitute(
{
for(std::size_t i = 0; i < substitutionIdentifiers.size(); ++i)
{
if (line.compare(lineColumn, substitutionIdentifiers[i].size(), substitutionIdentifiers[i]) != 0)
if(line.compare(lineColumn, substitutionIdentifiers[i].size(), substitutionIdentifiers[i]) != 0)
{
continue;
}
std::string const lineCopy = line;
line = lineCopy.substr(0, lineColumn) + substitutionValues[i];
if (lineCopy.size() > lineColumn + substitutionIdentifiers[i].size())
if(lineCopy.size() > lineColumn + substitutionIdentifiers[i].size())
{
line += lineCopy.substr(lineColumn + substitutionIdentifiers[i].size(), lineCopy.size());
}
@@ -27,13 +27,9 @@ bool trySubstitute(
return false;
}
void Preprocessor::extractComment(
std::string & line,
std::size_t const lineNumber,
std::size_t const lineColumn)
void Preprocessor::extractComment(std::string & line, std::size_t const lineNumber, std::size_t const lineColumn)
{
if (line.size() <= lineColumn + 1 ||
line.compare(lineColumn + 1, std::string::npos, "DEFINE") <= 0)
if(line.size() <= lineColumn + 1 || line.compare(lineColumn + 1, std::string::npos, "DEFINE") <= 0)
{
// No match or empty DEFINE statement
line = line.substr(0, lineColumn);
@@ -61,7 +57,7 @@ void Preprocessor::extractComment(
break;
case LookForArgumentEnd:
if (Utils::isWhitespaceCharacter(line[i]))
if(Utils::isWhitespaceCharacter(line[i]))
{
switch(argumentCount)
{
@@ -107,7 +103,7 @@ void Preprocessor::extractComment(
break;
}
if (argumentCount > 0)
if(argumentCount > 0)
{
substitutionIdentifiers.push_back(firstArgument);
substitutionValues.push_back(secondArgument);
@@ -120,14 +116,14 @@ void Preprocessor::processLine(std::string & line, std::size_t const lineNumber)
{
for(std::size_t i = 0; i < line.size(); ++i)
{
if (!Utils::isWhitespaceCharacter(line[i]))
if(!Utils::isWhitespaceCharacter(line[i]))
{
if (trySubstitute(line, i, substitutionIdentifiers, substitutionValues))
if(trySubstitute(line, i, substitutionIdentifiers, substitutionValues))
{
continue;
}
if (line[i] == '#')
if(line[i] == '#')
{
extractComment(line, lineNumber, i);
return;
@@ -151,9 +147,6 @@ void Preprocessor::printSubstitutions() const
{
for(std::size_t i = 0; i < substitutionIdentifiers.size(); ++i)
{
std::printf(
"%s -> %s\n",
substitutionIdentifiers[i].c_str(),
substitutionValues[i].c_str());
std::printf("%s -> %s\n", substitutionIdentifiers[i].c_str(), substitutionValues[i].c_str());
}
}

View File

@@ -3,8 +3,6 @@
namespace Token
{
TokenizationError::TokenizationError(Token const & token, std::string const & msg)
: errorToken(token),
errorMsg(msg)
{
}
: errorToken(token), errorMsg(msg)
{ }
}

View File

@@ -5,29 +5,28 @@ namespace Token
{
OperandType GetOperandType(std::string const & op)
{
static std::map<std::string, OperandType, std::less<>> const operations =
{
{ "addi", OperandType::AddInteger },
{ "subi", OperandType::SubtractInteger },
{ "divi", OperandType::DivideInteger },
{ "muli", OperandType::MultiplyInteger },
{ "shri", OperandType::ShiftIntegerRight },
{ "shli", OperandType::ShiftIntegerLeft },
{ "jmp", OperandType::Jump },
{ "call", OperandType::CallFunction },
{ "ret", OperandType::ReturnFromFunction },
{ "exit", OperandType::ExitProgram },
{ "lti", OperandType::LessThanInteger },
{ "gti", OperandType::GreaterThanInteger },
{ "eqi", OperandType::EqualInteger },
{ "seti", OperandType::SetInteger },
{ "int", OperandType::Interrupt },
{ "pushi", OperandType::PushInteger},
{ "popi", OperandType::PopInteger},
static std::map<std::string, OperandType, std::less<>> const operations = {
{"addi", OperandType::AddInteger},
{"subi", OperandType::SubtractInteger},
{"divi", OperandType::DivideInteger},
{"muli", OperandType::MultiplyInteger},
{"shri", OperandType::ShiftIntegerRight},
{"shli", OperandType::ShiftIntegerLeft},
{"jmp", OperandType::Jump},
{"call", OperandType::CallFunction},
{"ret", OperandType::ReturnFromFunction},
{"exit", OperandType::ExitProgram},
{"lti", OperandType::LessThanInteger},
{"gti", OperandType::GreaterThanInteger},
{"eqi", OperandType::EqualInteger},
{"seti", OperandType::SetInteger},
{"int", OperandType::Interrupt},
{"pushi", OperandType::PushInteger},
{"popi", OperandType::PopInteger},
};
auto const & result = operations.find(op);
if (result != operations.end())
if(result != operations.end())
{
return result->second;
}

View File

@@ -1,20 +1,15 @@
#include <token/registertype.hpp>
#include <map>
#include <token/registertype.hpp>
namespace Token
{
RegisterType GetRegisterType(std::string const & reg)
{
static std::map<std::string, RegisterType, std::less<>> const registers =
{
{ "A", RegisterType::A },
{ "B", RegisterType::B },
{ "C", RegisterType::C },
{ "D", RegisterType::D }
};
static std::map<std::string, RegisterType, std::less<>> const registers
= {{"A", RegisterType::A}, {"B", RegisterType::B}, {"C", RegisterType::C}, {"D", RegisterType::D}};
auto const & result = registers.find(reg);
if (result != registers.end())
if(result != registers.end())
{
return result->second;
}

View File

@@ -4,77 +4,60 @@
namespace Token
{
Token::Token(TokenType _type, bool validness, int const _lineNumber, int const _lineColumn)
: lineNumber(_lineNumber),
lineColumn(_lineColumn),
type(_type),
valueType(TokenValueType::None),
isValid(validness),
data(0),
errorMessage()
{
}
: lineNumber(_lineNumber), lineColumn(_lineColumn), type(_type), valueType(TokenValueType::None),
isValid(validness), data(0), errorMessage()
{ }
Token::Token(TokenType _type, std::string const & string, bool validness, int const _lineNumber, int const _lineColumn)
: lineNumber(_lineNumber),
lineColumn(_lineColumn),
type(_type),
valueType(TokenValueType::String),
isValid(validness),
data(string),
errorMessage()
{
}
Token::Token(
TokenType _type,
std::string const & string,
bool validness,
int const _lineNumber,
int const _lineColumn)
: lineNumber(_lineNumber), lineColumn(_lineColumn), type(_type), valueType(TokenValueType::String),
isValid(validness), data(string), errorMessage()
{ }
Token::Token(TokenType _type, int value, bool validness, int const _lineNumber, int const _lineColumn)
: lineNumber(_lineNumber),
lineColumn(_lineColumn),
type(_type),
valueType(TokenValueType::Integer),
isValid(validness),
data(value),
errorMessage()
{
}
: lineNumber(_lineNumber), lineColumn(_lineColumn), type(_type), valueType(TokenValueType::Integer),
isValid(validness), data(value), errorMessage()
{ }
Token::Token(TokenType _type, RegisterType const registerType, bool validness, int const _lineNumber, int const _lineColumn)
: lineNumber(_lineNumber),
lineColumn(_lineColumn),
type(_type),
valueType(TokenValueType::Register),
isValid(validness),
data(registerType),
errorMessage()
{
}
Token::Token(
TokenType _type,
RegisterType const registerType,
bool validness,
int const _lineNumber,
int const _lineColumn)
: lineNumber(_lineNumber), lineColumn(_lineColumn), type(_type), valueType(TokenValueType::Register),
isValid(validness), data(registerType), errorMessage()
{ }
Token::Token(TokenType _type, OperandType const operandType, bool validness, int const _lineNumber, int const _lineColumn)
: lineNumber(_lineNumber),
lineColumn(_lineColumn),
type(_type),
valueType(TokenValueType::Operand),
isValid(validness),
data(operandType),
errorMessage()
{
}
Token::Token(
TokenType _type,
OperandType const operandType,
bool validness,
int const _lineNumber,
int const _lineColumn)
: lineNumber(_lineNumber), lineColumn(_lineColumn), type(_type), valueType(TokenValueType::Operand),
isValid(validness), data(operandType), errorMessage()
{ }
Token::Token(Token const & other)
: lineNumber(other.lineNumber),
lineColumn(other.lineColumn),
type(other.type),
valueType(other.valueType),
isValid(other.isValid),
data(other.data),
errorMessage(other.errorMessage)
{
}
: lineNumber(other.lineNumber), lineColumn(other.lineColumn), type(other.type), valueType(other.valueType),
isValid(other.isValid), data(other.data), errorMessage(other.errorMessage)
{ }
Token Token::CreateEmptyToken(int const lineNumber, int const lineColumn)
{
return Token(TokenType::Unknown, false, lineNumber, lineColumn);
}
Token Token::CreateErrorToken(std::string const & message, TokenType const type, int const lineNumber, int const lineColumn)
Token Token::CreateErrorToken(
std::string const & message,
TokenType const type,
int const lineNumber,
int const lineColumn)
{
Token token(type, false, lineNumber, lineColumn);
token.errorMessage = message;
@@ -113,7 +96,7 @@ namespace Token
Token Token::CreateMemoryToken(RegisterType const registerType, int const lineNumber, int const lineColumn)
{
if (registerType == RegisterType::Unknown)
if(registerType == RegisterType::Unknown)
{
return CreateErrorToken("Unknown register used", TokenType::Register, lineNumber, lineColumn);
}
@@ -161,7 +144,7 @@ namespace Token
switch(type)
{
case TokenType::ImmediateInteger:
if (isValid)
if(isValid)
{
std::printf("%i", std::get<int>(data));
}
@@ -172,7 +155,7 @@ namespace Token
break;
case TokenType::Operand:
if (isValid)
if(isValid)
{
OperandType const opType = std::get<OperandType>(data);
switch(opType)
@@ -193,7 +176,7 @@ namespace Token
break;
case TokenType::Register:
if (isValid)
if(isValid)
{
RegisterType const regType = std::get<RegisterType>(data);
switch(regType)

View File

@@ -20,16 +20,14 @@ namespace Token
}
}
Token GetCharacterLiteralToken(
std::string const & token,
std::size_t const lineNumber,
std::size_t const lineColumn)
Token
GetCharacterLiteralToken(std::string const & token, std::size_t const lineNumber, std::size_t const lineColumn)
{
for(std::size_t i = 1; i < token.size(); ++i)
{
if (token[i] == '\'')
if(token[i] == '\'')
{
if (i != 2)
if(i != 2)
{
return Token::CreateErrorToken(
"Character literal must be exactly 1 character long between single quotes",
@@ -39,10 +37,7 @@ namespace Token
}
else
{
return Token::CreateImmediateValueToken(
token[1],
lineNumber,
lineColumn + 1);
return Token::CreateImmediateValueToken(token[1], lineNumber, lineColumn + 1);
}
}
}
@@ -54,10 +49,7 @@ namespace Token
lineColumn);
}
Token GetMemoryToken(
std::string const & token,
std::size_t const lineNumber,
std::size_t const lineColumn)
Token GetMemoryToken(std::string const & token, std::size_t const lineNumber, std::size_t const lineColumn)
{
// Minimal example: [$1] or [%A]
if(token.size() < 4)
@@ -69,7 +61,7 @@ namespace Token
lineColumn);
}
if (token[0] != '[' || token[token.size() - 1] != ']')
if(token[0] != '[' || token[token.size() - 1] != ']')
{
return Token::CreateErrorToken(
"Non terminated memory address brackets",
@@ -80,16 +72,13 @@ namespace Token
char const memoryPrefix = token[1];
std::string const valueString = token.substr(2, token.size() - 3u);
if (memoryPrefix == '$')
if(memoryPrefix == '$')
{
auto const result = TryParseInt(valueString);
if (result.has_value())
if(result.has_value())
{
return Token::CreateMemoryToken(
result.value(),
lineNumber,
lineColumn);
return Token::CreateMemoryToken(result.value(), lineNumber, lineColumn);
}
return Token::CreateErrorToken(
@@ -98,12 +87,9 @@ namespace Token
lineNumber,
lineColumn);
}
else if (memoryPrefix == '%')
else if(memoryPrefix == '%')
{
return Token::CreateMemoryToken(
GetRegisterType(valueString),
lineNumber,
lineColumn);
return Token::CreateMemoryToken(GetRegisterType(valueString), lineNumber, lineColumn);
}
return Token::CreateErrorToken(
@@ -113,9 +99,7 @@ namespace Token
lineColumn + 1u);
}
Token GetUnterminatedCharacterLiteralError(
std::size_t const lineNumber,
std::size_t const lineColumn)
Token GetUnterminatedCharacterLiteralError(std::size_t const lineNumber, std::size_t const lineColumn)
{
return Token::CreateErrorToken(
"Unterminated character or string literal",
@@ -136,12 +120,9 @@ namespace Token
{
auto const result = TryParseInt(string.substr(1, string.size()));
if (result.has_value())
if(result.has_value())
{
return Token::CreateImmediateValueToken(
result.value(),
lineNumber,
lineColumn);
return Token::CreateImmediateValueToken(result.value(), lineNumber, lineColumn);
}
return Token::CreateErrorToken(
@@ -152,8 +133,8 @@ namespace Token
}
case '%':
return Token::CreateRegisterToken(GetRegisterType(
string.substr(1, string.size())),
return Token::CreateRegisterToken(
GetRegisterType(string.substr(1, string.size())),
lineNumber,
lineColumn);
@@ -178,10 +159,7 @@ namespace Token
case ':':
// TODO check if label is an Operand?
return Token::CreateLabelDefinitionToken(
string.substr(0, string.size() - 1),
lineNumber,
lineColumn);
return Token::CreateLabelDefinitionToken(string.substr(0, string.size() - 1), lineNumber, lineColumn);
case '\'':
case '\"':
@@ -190,7 +168,7 @@ namespace Token
}
OperandType const opType = GetOperandType(string);
if (opType != OperandType::Unknown)
if(opType != OperandType::Unknown)
{
return Token::CreateOperandToken(opType, lineNumber, lineColumn);
}
@@ -199,14 +177,11 @@ namespace Token
return Token::CreateLabelArgumentToken(string, lineNumber, lineColumn);
}
void Tokenizer::Tokenize(
std::string const & line,
std::size_t const lineNumber,
std::vector<Token> & tokens)
void Tokenizer::Tokenize(std::string const & line, std::size_t const lineNumber, std::vector<Token> & tokens)
{
for(std::size_t column = 0u; column < line.size(); ++column)
{
if (Utils::isWhitespaceCharacter(line[column]))
if(Utils::isWhitespaceCharacter(line[column]))
{
continue;
}
@@ -216,19 +191,15 @@ namespace Token
case '\'':
case '\"':
{
auto const result = Utils::getValueSurroundedBy(
line,
column,
line[column]);
if (result.has_value())
auto const result = Utils::getValueSurroundedBy(line, column, line[column]);
if(result.has_value())
{
tokens.push_back(ExtractToken(result.value(), lineNumber, column));
column += result.value().size() - 1;
}
else
{
tokens.push_back(
GetUnterminatedCharacterLiteralError(lineNumber, column));
tokens.push_back(GetUnterminatedCharacterLiteralError(lineNumber, column));
// Parsing must stop here, the line is malformed
return;
@@ -244,9 +215,9 @@ namespace Token
{
auto const result = Utils::getValueSurroundedByWhitespace(line, column);
auto const lastCharacterIndex = result.size() - 1;
if (result[lastCharacterIndex] == ';')
if(result[lastCharacterIndex] == ';')
{
tokens.push_back(ExtractToken(result.substr(0, result.size() -1), lineNumber, column));
tokens.push_back(ExtractToken(result.substr(0, result.size() - 1), lineNumber, column));
tokens.push_back(ExtractToken(";", lineNumber, column + lastCharacterIndex));
}
else

View File

@@ -2,19 +2,14 @@
namespace Utils
{
bool isWhitespaceCharacter(char const c)
{
return c == '\n' || c == ' ' || c == '\t' || c == '\r';
}
bool isWhitespaceCharacter(char const c) { return c == '\n' || c == ' ' || c == '\t' || c == '\r'; }
std::optional<std::string> getValueSurroundedBy(
std::string const & src,
std::size_t const pos,
char const surroundingCharacter)
std::optional<std::string>
getValueSurroundedBy(std::string const & src, std::size_t const pos, char const surroundingCharacter)
{
for(std::size_t i = pos + 1; i < src.size(); ++i)
{
if (src[i] == surroundingCharacter)
if(src[i] == surroundingCharacter)
{
return std::make_optional(src.substr(pos, (i + 1) - pos));
}
@@ -23,13 +18,11 @@ namespace Utils
return std::nullopt;
}
std::string getValueSurroundedByWhitespace(
std::string const & src,
std::size_t const pos)
std::string getValueSurroundedByWhitespace(std::string const & src, std::size_t const pos)
{
for(std::size_t i = pos + 1; i < src.size(); ++i)
{
if (isWhitespaceCharacter(src[i]))
if(isWhitespaceCharacter(src[i]))
{
return src.substr(pos, i - pos);
}
@@ -40,10 +33,7 @@ namespace Utils
namespace Bytes
{
void Write(
int const value,
std::vector<std::uint8_t> & vec,
std::size_t const pos)
void Write(int const value, std::vector<std::uint8_t> & vec, std::size_t const pos)
{
vec[pos] = value & 0xFF;
vec[pos + 1] = (value >> 8) & 0xFF;

View File

@@ -8,9 +8,7 @@
void PrintBadToken(Token::Token const & token, std::vector<std::string> const & lines)
{
std::printf("at line number %i, column %i: ",
token.lineNumber + 1,
token.lineColumn + 1);
std::printf("at line number %i, column %i: ", token.lineNumber + 1, token.lineColumn + 1);
std::puts(token.errorMessage.c_str());
std::printf("%s\n", lines[token.lineNumber].c_str());
@@ -30,7 +28,7 @@ void PrintTokenError(Token::TokenizationError const & err, std::vector<std::stri
bool Wassembler::LoadTextFile(std::string const & filePath, std::vector<std::string> & lines) const
{
std::ifstream input(filePath);
if (!input.is_open())
if(!input.is_open())
{
return false;
}
@@ -49,7 +47,7 @@ bool Wassembler::Preprocess(std::vector<std::string> & lines) const
{
Preprocessor preprocessor;
preprocessor.process(lines);
if (printSubstitutions)
if(printSubstitutions)
{
preprocessor.printSubstitutions();
}
@@ -74,13 +72,13 @@ bool Wassembler::Tokenize(std::vector<std::string> const & lines, std::vector<To
}
}
if (printTokens && tokens.size() > 0)
if(printTokens && tokens.size() > 0)
{
int previousLine = tokens[0].lineNumber;
std::printf("Line %04i: ", previousLine);
for(auto const & token : tokens)
for(auto const & token: tokens)
{
if (token.lineNumber != previousLine)
if(token.lineNumber != previousLine)
{
std::putc('\n', stdout);
previousLine = token.lineNumber;
@@ -94,9 +92,9 @@ bool Wassembler::Tokenize(std::vector<std::string> const & lines, std::vector<To
// Validate the syntax
bool syntaxError = false;
for(auto const & token : tokens)
for(auto const & token: tokens)
{
if (!token.isValid)
if(!token.isValid)
{
std::printf("Syntax error ");
PrintBadToken(token, lines);
@@ -135,12 +133,10 @@ void Wassembler::ExecuteCode(std::vector<uint8_t> const & bytes)
vm.Run();
}
bool Wassembler::CompileFile(
std::string const & filePath,
std::vector<std::uint8_t> & bytes) const
bool Wassembler::CompileFile(std::string const & filePath, std::vector<std::uint8_t> & bytes) const
{
std::vector<std::string> lines;
if (!LoadTextFile(filePath, lines))
if(!LoadTextFile(filePath, lines))
{
std::printf("Error: Cannot open file %s for reading", filePath.c_str());
return false;
@@ -153,7 +149,7 @@ bool Wassembler::CompileFile(
}
std::vector<Token::Token> tokens;
if (!Tokenize(lines, tokens) || !CompileToBytes(tokens, lines, bytes))
if(!Tokenize(lines, tokens) || !CompileToBytes(tokens, lines, bytes))
{
std::puts("Aborting due to syntax error(s)");
return false;
@@ -162,33 +158,21 @@ bool Wassembler::CompileFile(
return true;
}
void Wassembler::SetMemorySize(unsigned const size)
{
vm.SetMemorySize(size);
}
void Wassembler::SetMemorySize(unsigned const size) { vm.SetMemorySize(size); }
void Wassembler::EnableSubstitutionsLogging()
{
printSubstitutions = true;
}
void Wassembler::EnableSubstitutionsLogging() { printSubstitutions = true; }
void Wassembler::EnableTokensLogging()
{
printTokens = true;
}
void Wassembler::EnableTokensLogging() { printTokens = true; }
void Wassembler::EnableByteTranslationLogging()
{
printTranslatedBytes = true;
}
void Wassembler::EnableByteTranslationLogging() { printTranslatedBytes = true; }
bool Wassembler::CompileAndRun(std::string const & filePath)
{
std::vector<std::uint8_t> bytes;
if (filePath.size() > 4 && filePath.compare(filePath.size() - 4, 4, ".bin") == 0)
if(filePath.size() > 4 && filePath.compare(filePath.size() - 4, 4, ".bin") == 0)
{
std::ifstream inputFile(filePath);
if (!inputFile.is_open())
if(!inputFile.is_open())
{
std::printf("Error: Cannot open file %s for reading", filePath.c_str());
return false;
@@ -196,7 +180,7 @@ bool Wassembler::CompileAndRun(std::string const & filePath)
std::size_t previousSize = 0;
bytes.resize(100);
while(inputFile.read(reinterpret_cast<char*>(&bytes[previousSize]), 100))
while(inputFile.read(reinterpret_cast<char *>(&bytes[previousSize]), 100))
{
previousSize = bytes.size();
bytes.resize(bytes.size() + 100);
@@ -204,19 +188,16 @@ bool Wassembler::CompileAndRun(std::string const & filePath)
bytes.resize(bytes.size() - (100 - inputFile.gcount()));
}
else if (filePath.size() > 5 &&
filePath.compare(filePath.size() - 5, 5, ".wasm") == 0)
else if(filePath.size() > 5 && filePath.compare(filePath.size() - 5, 5, ".wasm") == 0)
{
if (!CompileFile(filePath, bytes))
if(!CompileFile(filePath, bytes))
{
return false;
}
}
else
{
std::printf(
"Error: unrecognized file extension on input file %s",
filePath.c_str());
std::printf("Error: unrecognized file extension on input file %s", filePath.c_str());
return false;
}
@@ -225,7 +206,7 @@ bool Wassembler::CompileAndRun(std::string const & filePath)
{
ExecuteCode(bytes);
}
catch (Execute::RuntimeError const & e)
catch(Execute::RuntimeError const & e)
{
std::puts(e.GetMessage().c_str());
std::puts("Aborting due to runtime error(s)");
@@ -235,24 +216,22 @@ bool Wassembler::CompileAndRun(std::string const & filePath)
return true;
}
bool Wassembler::CompileToFile(
std::string const & inputFilePath,
std::string const & outputFilePath)
bool Wassembler::CompileToFile(std::string const & inputFilePath, std::string const & outputFilePath)
{
std::vector<std::uint8_t> bytes;
if (!CompileFile(inputFilePath, bytes))
if(!CompileFile(inputFilePath, bytes))
{
return false;
}
std::ofstream output(outputFilePath, std::ios::binary | std::ios::trunc);
if (!output.is_open())
if(!output.is_open())
{
std::printf("Error: Cannot open file %s for writing", outputFilePath.c_str());
return false;
}
if (!output.write(reinterpret_cast<char*>(bytes.data()), bytes.size()))
if(!output.write(reinterpret_cast<char *>(bytes.data()), bytes.size()))
{
std::printf("Error: An error occurred whilst writing to %s", outputFilePath.c_str());
return false;