diff options
Diffstat (limited to 'hobgoblin/src')
| -rw-r--r-- | hobgoblin/src/patio.hob | 84 | ||||
| -rw-r--r-- | hobgoblin/src/patio/instructions.hob | 253 | ||||
| -rw-r--r-- | hobgoblin/src/patio/operands.hob | 39 | ||||
| -rw-r--r-- | hobgoblin/src/patio/types.hob | 123 | ||||
| -rw-r--r-- | hobgoblin/src/patio/values.hob | 43 |
5 files changed, 542 insertions, 0 deletions
diff --git a/hobgoblin/src/patio.hob b/hobgoblin/src/patio.hob index e69de29b..5a2d0734 100644 --- a/hobgoblin/src/patio.hob +++ b/hobgoblin/src/patio.hob @@ -0,0 +1,84 @@ +import {Source} from ./sources; +import {PatioInstruction} from ./patio/instructions; +import {PatioDataLayout, PatioDataValue, PatioType} from ./patio/types; + +// == Compilation units == + +struct PatioCompilationUnit { + field elements: List[PatioCompilationUnitElement]; + field source: Source; +} + +// == Compilation unit elements == + +sum PatioCompilationUnitElement { + variant PatioDataElementImmutableDefinition; + variant PatioDataElementMutableDeclaration; + variant PatioDataElementMutableDefinition; + variant PatioExceptionTypeDefinition; + variant PatioFunctionDeclaration; + variant PatioFunctionDefinition; +} + +struct PatioDataElementImmutableDefinition { + field name: String; + field visibility: PatioVisibility; + field value: PatioDataValue; + field source: Source; +} + +struct PatioDataElementMutableDeclaration { + field name: String; + field layout: PatioDataLayout; + field source: Source; +} + +struct PatioDataElementMutableDefinition { + field name: String; + field visibility: PatioVisibility; + field initialValue: PatioDataValue; + field source: Source; +} + +struct PatioExceptionTypeDefinition { + field name: String; + field valueType: PatioType; + field source: Source; +} + +struct PatioFunctionDeclaration { + field name: String; + field params: List[PatioLocal]; + field returnTypes: List[PatioType]; + field source: Source; +} + +struct PatioFunctionDefinition { + field name: String; + field visibility: PatioVisibility; + field locals: List[PatioLocal]; + field returnTypes: List[PatioType]; + field body: List[PatioInstruction]; + field source: Source; +} + +// == Visibility == + +enum PatioVisibility { + variant private; + variant public; +} + +// == Locals == + +struct PatioLocal { + field name: String; + field type: PatioType; + field localType: PatioLocalType; +} + +enum PatioLocalType { + variant param; + variant val; + variant var; +} diff --git a/hobgoblin/src/patio/instructions.hob b/hobgoblin/src/patio/instructions.hob new file mode 100644 index 00000000..c6f33976 --- /dev/null +++ b/hobgoblin/src/patio/instructions.hob @@ -0,0 +1,253 @@ +import {Source} from ../sources; +import {PatioLocalRef, PatioOperand} from ./operands; +import {PatioDataLayout} from ./types; + +sum PatioInstruction { + variant PatioBlock; + variant PatioBoolToInt; + variant PatioCall; + variant PatioCallPointer; + variant PatioDataPtrToInt; + variant PatioIf; + variant PatioIntAdd; + variant PatioIntEquals; + variant PatioIntNotEqual; + variant PatioIntSub; + variant PatioIntToBool; + variant PatioIntToDataPtr; + variant PatioLocalStore; + variant PatioLoop; + variant PatioLoopBreak; + variant PatioLoopContinue; + variant PatioMemoryLoad; + variant PatioMemoryStore; + variant PatioReturn; + variant PatioSwitch; + variant PatioThrow; + variant PatioTry; + variant PatioUnreachable; + variant PatioVarLoad; + variant PatioVarStore; +} + +/// Execute the instructions in the body of the block. The results may be used in +/// the parent scope, but any other variables (as distinct from values) are no +/// longer in use. +struct PatioBlock { + field body: List[PatioInstruction]; + field results: List[PatioOperand]; + field source: Source; +} + +struct PatioBoolToInt { + field destination: PatioLocalRef; + field value: PatioOperand; + field source: Source; +} + +/// Call the function with the given name, and store the returned values in the +/// destination locals. +struct PatioCall { + field destinations: List[PatioLocalRef]; + field functionName: String; + field args: List[PatioOperand]; + field source: Source; +} + +/// Call the function pointed to by the function pointer with the given +/// arguments, and store the returned values in the destination locals. +struct PatioCallPointer { + field destinations: List[PatioLocalRef]; + field functionPointer: PatioOperand; + field args: List[PatioOperand]; + field source: Source; +} + +struct PatioDataPtrToInt { + field destination: PatioLocalRef; + field value: PatioOperand; + field source: Source; +} + +/// If the condition is true, execute the instructions in the "true" body, +/// otherwise execute the instructions in the "false" body. +/// +/// Each block must have the same number of results as destinations. Each result is +/// assigned to the destination with the same index. +struct PatioIf { + field destinations: List[PatioLocalRef]; + field condition: PatioOperand; + field trueBody: PatioBlock; + field falseBody: PatioBlock; + field source: Source; +} + +struct PatioIntAdd { + field destination: PatioLocalRef; + field left: PatioOperand; + field right: PatioOperand; + field source: Source; +} + +struct PatioIntEquals { + field destination: PatioLocalRef; + field left: PatioOperand; + field right: PatioOperand; + field source: Source; +} + +/// Compare the left and right operands. If they are equal, store false in the +/// destination, otherwise store true in the destination. +struct PatioIntNotEqual { + field destination: PatioLocalRef; + field left: PatioOperand; + field right: PatioOperand; + field source: Source; +} + +/// Calculate the left operand minus the right operand, and store the result in +/// the destination. +struct PatioIntSub { + field destination: PatioLocalRef; + field left: PatioOperand; + field right: PatioOperand; + field source: Source; +} + +struct PatioIntToBool { + field destination: PatioLocalRef; + field value: PatioOperand; + field source: Source; +} + +struct PatioIntToDataPtr { + field destination: PatioLocalRef; + field value: PatioOperand; + field source: Source; +} + +/// Store the given value in the destination local. +struct PatioLocalStore { + field destination: PatioLocalRef; + field value: PatioOperand; + field source: Source; +} + +/// Execute the body. The `continue` instruction can jump back to the +/// start of the body. The `break` instruction can jump to the end of +/// the body. +struct PatioLoop { + field body: List[PatioInstruction]; + field source: Source; +} + +/// Jump to the end of the enclosing `loop` instruction's body. +struct PatioLoopBreak { + field source: Source; +} + +/// Jump to the start of the enclosing `loop` instruction's body. +struct PatioLoopContinue { + field source: Source; +} + +/// Load the value at the given offset from the given pointer and store it in the +/// destination local. +struct PatioMemoryLoad { + field destination: PatioLocalRef; + field pointer: PatioOperand; + field layout: PatioDataLayout; + field elementOffsets: List[Int32]; + field source: Source; +} + +/// Store the given value at the given offset from the given pointer. +struct PatioMemoryStore { + field pointer: PatioOperand; + field layout: PatioDataLayout; + field elementOffsets: List[Int32]; + field value: PatioOperand; + field source: Source; +} + +/// Return with the given values from the current function. +struct PatioReturn { + field values: List[PatioOperand]; + field source: Source; +} + +/// Find a case with a value matching that of the instruction's value. If such a +/// case is found, execute the body of that case, otherwise execute the default +/// body. +/// +/// Each block must have the same number of results as destinations. Each result +/// is assigned to the destination with the same index. +struct PatioSwitch { + field destinations: List[PatioLocalRef]; + field value: PatioOperand; + field cases: List[PatioSwitchCase]; + field defaultBody: PatioBlock; + field source: Source; +} + +struct PatioSwitchCase { + field value: Int32; + field body: PatioBlock; + field source: Source; +} + +/// Search the stack for an exception handler with a catch clause matching the +/// thrown exception type. Unwind the stack up to and including this exception +/// handler, and run the body of the catch clause. If no such exception handler +/// is found, the process should abort. +struct PatioThrow { + field exceptionTypeName: String; + field value: PatioOperand; + field source: Source; +} + +/// Push an exception handler with the given catch clauses onto the control flow +/// stack, and then execute the instructions in its body. +/// +/// If the exception handler catches an exception, the body of the corresponding +/// is executed instead. +/// +/// Each block (that is, the body of the try and the body of each catch clause) +/// must have the same number of results as destinations. Each result is assigned to +/// the destination with the same index. +struct PatioTry { + field destinations: List[PatioLocalRef]; + field catchClauses: List[PatioCatchClause]; + field body: PatioBlock; + field source: Source; +} + +/// A catch clause can accept an exception of a given type. If executed, it will +/// stored the value of the exception in the given destination, and then execute the +/// body. +struct PatioCatchClause { + field exceptionTypeName: String; + field destination: PatioLocalRef; + field body: PatioBlock; + field source: Source; +} + +/// Unreachable instructions have undefined behaviour, and are used to indicate +/// that an instruction sequence is unreachable. +struct PatioUnreachable { + field source: Source; +} + +/// Load the value from the given var and store it in the destination local. +struct PatioVarLoad { + field destination: PatioLocalRef; + field var: PatioLocalRef; + field source: Source; +} + +/// Store the given value in the destination var. +struct PatioVarStore { + field var: PatioLocalRef; + field value: PatioOperand; + field source: Source; +} diff --git a/hobgoblin/src/patio/operands.hob b/hobgoblin/src/patio/operands.hob new file mode 100644 index 00000000..5a8769f7 --- /dev/null +++ b/hobgoblin/src/patio/operands.hob @@ -0,0 +1,39 @@ +import {PatioDataPtrValue, PatioIntValue} from ./values; + +sum PatioOperand { + variant PatioLocalRef; + variant PatioBoolConst; + variant PatioByteConst; + variant PatioDataPtrConst; + variant PatioFunctionPtrConst; + variant PatioInt32Const; + variant PatioIntConst; +} + +struct PatioLocalRef { + field name: String; +} + +struct PatioBoolConst { + field value: Bool; +} + +struct PatioByteConst { + field value: Int8; +} + +struct PatioDataPtrConst { + field value: PatioDataPtrValue; +} + +struct PatioFunctionPtrConst { + field name: String; +} + +struct PatioInt32Const { + field value: PatioIntValue; +} + +struct PatioIntConst { + field value: PatioIntValue; +} diff --git a/hobgoblin/src/patio/types.hob b/hobgoblin/src/patio/types.hob new file mode 100644 index 00000000..3155e576 --- /dev/null +++ b/hobgoblin/src/patio/types.hob @@ -0,0 +1,123 @@ +import {PatioDataPtrValue, PatioIntValue} from ./values; + +// == Types == + +sum PatioType { + variant PatioBoolType; + variant PatioByteType; + variant PatioDataPtrType; + variant PatioFunctionPtrType; + variant PatioInt32Type; + variant PatioIntType; +} + +struct PatioBoolType { + singleton; +} + +struct PatioByteType { + singleton; +} + +struct PatioDataPtrType { + singleton; +} + +struct PatioFunctionPtrType { + singleton; +} + +struct PatioInt32Type { + singleton; +} + +struct PatioIntType { + singleton; +} + +// == Data layouts == + +sum PatioDataLayout { + variant PatioDataLayoutArray; + variant PatioDataLayoutBool; + variant PatioDataLayoutByte; + variant PatioDataLayoutDataPtr; + variant PatioDataLayoutFunctionPtr; + variant PatioDataLayoutInt; + variant PatioDataLayoutInt32; + variant PatioDataLayoutStruct; +} + +struct PatioDataLayoutArray { + field element: PatioDataLayout; + field size: Int32; +} + +struct PatioDataLayoutBool { + singleton; +} + +struct PatioDataLayoutByte { + singleton; +} + +struct PatioDataLayoutDataPtr { + singleton; +} + +struct PatioDataLayoutFunctionPtr { + singleton; +} + +struct PatioDataLayoutInt { + singleton; +} + +struct PatioDataLayoutInt32 { + singleton; +} + +struct PatioDataLayoutStruct { + field elements: List[PatioDataLayout]; +} + +// == Data values == + +sum PatioDataValue { + variant PatioDataValueArray; + variant PatioDataValueBool; + variant PatioDataValueByte; + variant PatioDataValueDataPtr; + variant PatioDataValueInt; + variant PatioDataValueInt32; + variant PatioDataValueStruct; +} + +struct PatioDataValueArray { + field elementLayout: PatioDataLayout; + field elements: List[PatioDataValue]; +} + +struct PatioDataValueBool { + field value: Bool; +} + +struct PatioDataValueByte { + field value: Int8; +} + +struct PatioDataValueDataPtr { + field value: PatioDataPtrValue; +} + +struct PatioDataValueInt { + field value: PatioIntValue; +} + +struct PatioDataValueInt32 { + field value: PatioIntValue; +} + +struct PatioDataValueStruct { + field elements: List[PatioDataValue]; +} diff --git a/hobgoblin/src/patio/values.hob b/hobgoblin/src/patio/values.hob new file mode 100644 index 00000000..0e14cf35 --- /dev/null +++ b/hobgoblin/src/patio/values.hob @@ -0,0 +1,43 @@ +import {PatioDataLayout} from ./types; + +// == Data ptr values == + +sum PatioDataPtrValue { + variant PatioDataPtrValueDataElement; + variant PatioDataPtrValueNull; +} + +struct PatioDataPtrValueDataElement { + field name: String; +} + +struct PatioDataPtrValueNull { +} + +// == Int values == + +/// An int value that is a constant in the compiled program, but may differ +/// across targets. +sum PatioIntValue { + variant PatioIntValueByteOffsetOf; + variant PatioIntValueByteSizeOf; + variant PatioIntValueLiteral; +} + +/// The offset, in bytes, of an offset in a data layout. +struct PatioIntValueByteOffsetOf { + field layout: PatioDataLayout; + field elementOffsets: List[Int32]; +} + +/// The size, in bytes, of a data layout. +struct PatioIntValueByteSizeOf { + field layout: PatioDataLayout; +} + +/// An int value that is the same across all targets. +struct PatioIntValueLiteral { + field value: Int32; +} + + |
