Skip to content

Commit

Permalink
Insert (auto-derived) ->TypeID() into all interfaces, add `typeid:(…
Browse files Browse the repository at this point in the history
…ClassName)` to get a typeid without an instance
  • Loading branch information
CloakerSmoker committed May 22, 2024
1 parent 049153b commit 6fca3b2
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 8 deletions.
Binary file modified build/freebsd_compiler.elf
Binary file not shown.
Binary file modified build/linux_compiler.elf
Binary file not shown.
Binary file modified build/windows_compiler.exe
Binary file not shown.
2 changes: 2 additions & 0 deletions src/compiler/Parser.rlx
Original file line number Diff line number Diff line change
Expand Up @@ -2387,6 +2387,8 @@ struct ParserState {
InterfaceInfo* Info := InterfaceInfo:New()
NewType->InterfaceInfo := Info

this->AddDeriveableMethod(NewType, "TypeID", "virtual i64 TypeID()", this->i64->AsNonPointer(), NewType->AsPointer(1))

this->Consume(TOKEN_TYPE_PUNCTUATION, PUNCTUATION_OPEN_BRACE, "Expected '{' for interface body")

loop {
Expand Down
30 changes: 27 additions & 3 deletions src/compiler/Parser/Expression.rlx
Original file line number Diff line number Diff line change
Expand Up @@ -254,24 +254,50 @@

define ASTNode* TryParseFunctionCall(Token* NameToken, HashMap* FunctionNamespace, ASTNode* ThisParameter, i8** ErrorMessage) {
i8 HasFollowingColon := false
i8 IsTypeID := false

SafeString* Name := NameToken->StringValue

if (this->NextTokenMatches(TOKEN_TYPE_OPERATOR, OPERATOR_COLON)) {
; `NonTypeName` followed by `:`, must be a legacy built-in call

HasFollowingColon := true

IsTypeID := Name->Equals("typeid")
}

if !(this->NextTokenMatches(TOKEN_TYPE_PUNCTUATION, PUNCTUATION_OPEN_PAREN)) {
*ErrorMessage := "Expected opening `(` for function call."
return null
}

if (IsTypeID) {
ASTNode* TargetTypeNode := this->ParseTypeNode()
Type TargetType := TargetTypeNode->ValueType
TypeInfo* TargetBase := GetBaseType(TargetType)

Token* Tail := this->Consume(TOKEN_TYPE_PUNCTUATION, PUNCTUATION_CLOSE_PAREN, "Expected closing parenthesis after TypeID parameter")

if (GetPointerDepth(TargetType) != 0) {
TargetTypeNode->Error("Expected non-pointer type")
}
else if (TargetBase->Kind != TYPE_KIND_STRUCTURE || !TargetBase->IsClass) {
TargetTypeNode->Error("Expected class type")
}

ASTNode* ResultNode := ASTNode:New(NODE_TYPE_INTEGER, TargetBase->GetTypeID(), this->i64->AsNonPointer())

ResultNode~>Context->Clone(NameToken~>Context)->Merge(Tail~>Context)

return ResultNode
}

i8 ParameterCount := 0

if (ThisParameter != null) {
ParameterCount += 1
}

ASTNode** Parameters := this->ParseParameterList(&ParameterCount)

SourceContext* FirstTokenContext := NameToken~>Context
Expand All @@ -284,8 +310,6 @@
CallExpression* Result := null
ASTNode* ResultNode := ASTNode:NewCallNode(Parameters, ParameterCount, &Result, FirstTokenContext, this->GetCurrentTokenContext())

SafeString* Name := NameToken->StringValue

if (HasFollowingColon) {
; If we've matched the `name:` format, but not `name:other`, then we need to convert `name`
; into a specific built-in function identifier, and just return the result node.
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/Parser/Types.rlx
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ struct TypeInfo {
}

i8[100] Buffer
i32 Length := FormatString(Buffer, 100, "%t", this)
i32 Length := FormatString(Buffer, 100, "%t", this->AsNonPointer())

this->CachedTypeID := FNV1A(Buffer, Length)

Expand Down
14 changes: 12 additions & 2 deletions tests/complex_interfaces.out
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,15 @@ Single Parameter New: Complicated.New(30) : 30 40
Double Parameter New: Complicated.New(50, 60): 50 60

Default Method Implementation:
Boring->GetFavoriteNumber(): IDefineDefaults.GetFavoriteNumber(): 70
Opinionated->GetFavoriteNumber(): Opinionated.GetFavoriteNumber(): 80
B ->GetFavoriteNumber(): IDefineDefaults.GetFavoriteNumber(): 70
BO->GetFavoriteNumber(): IDefineDefaults.GetFavoriteNumber(): 70
O ->GetFavoriteNumber(): Opinionated.GetFavoriteNumber(): 80
OD->GetFavoriteNumber(): Opinionated.GetFavoriteNumber(): 80

TypeID:
B->TypeID() : 0x401FC6B3A30D0D4
typeid:(Boring): 0x401FC6B3A30D0D4
BD->TypeID() : 0x401FC6B3A30D0D4
O->TypeID() : 0xC43503884CB69701
typeid:(Opinionated): 0xC43503884CB69701
OD->TypeID() : 0xC43503884CB69701
22 changes: 20 additions & 2 deletions tests/complex_interfaces.rlx
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,32 @@ define i32 Main() {
Print("\nDefault Method Implementation:\n")

Boring* B := Boring:Allocate()
Print("Boring->GetFavoriteNumber(): ")
IDefineDefaults* BD := B
Print("B ->GetFavoriteNumber(): ")
i32 Favorite := B->GetFavoriteNumber()
Print(": %i\n", Favorite)
Print("BO->GetFavoriteNumber(): ")
i32 Favorite := BD->GetFavoriteNumber()
Print(": %i\n", Favorite)

Opinionated* O := Opinionated:Allocate()
Print("Opinionated->GetFavoriteNumber(): ")
IDefineDefaults* OD := O
Print("O ->GetFavoriteNumber(): ")
i32 Favorite := O->GetFavoriteNumber()
Print(": %i\n", Favorite)
Print("OD->GetFavoriteNumber(): ")
i32 Favorite := OD->GetFavoriteNumber()
Print(": %i\n", Favorite)

Print("\nTypeID:\n")

Print("B->TypeID() : %x\n", B->TypeID())
Print("typeid:(Boring): %x\n", typeid:(Boring))
Print("BD->TypeID() : %x\n", BD->TypeID())

Print("O->TypeID() : %x\n", O->TypeID())
Print("typeid:(Opinionated): %x\n", typeid:(Opinionated))
Print("OD->TypeID() : %x\n", OD->TypeID())

return 0
}

0 comments on commit 6fca3b2

Please sign in to comment.