From d2e228e578c51ea828d50daf847e64442f597de1 Mon Sep 17 00:00:00 2001 From: tacherasasi Date: Wed, 25 Jun 2025 08:48:07 +0300 Subject: [PATCH 1/4] Add dereference and address-of operations for pointers in evalPrefixExpression --- evaluator/prefix.go | 16 ++++++++++++++++ token/token.go | 1 + 2 files changed, 17 insertions(+) diff --git a/evaluator/prefix.go b/evaluator/prefix.go index f46ca91..752319f 100644 --- a/evaluator/prefix.go +++ b/evaluator/prefix.go @@ -37,6 +37,22 @@ func evalPrefixExpression(operator string, right object.Object, line int) object return evalMinusPrefixOperatorExpression(right, line) case "+": return evalPlusPrefixOperatorExpression(right, line) + case "*": + if right == nil { + return newError("Line %d: cannot dereference nil", line) + } + if p, ok := right.(*object.Pointer); ok { + if p.Ref == nil { + return newError("Line %d: pointer is nil", line) + } + return p.Ref + } + return newError("Line %d: cannot dereference non-pointer", line) + case "&": + if right == nil { + return newError("Line %d: cannot take address of nil", line) + } + return &object.Pointer{Ref: right} default: return newError("Mstari %d: Operesheni Haieleweki: %s%s", line, operator, right.Type()) } diff --git a/token/token.go b/token/token.go index 18c4f6a..5d3f130 100644 --- a/token/token.go +++ b/token/token.go @@ -26,6 +26,7 @@ const ( MINUS = "-" BANG = "!" ASTERISK = "*" + AMPERSAND = "&" POW = "**" SLASH = "/" MODULUS = "%" From 2937a40e77d38bb59846735f3e4ab4e993a59a3e Mon Sep 17 00:00:00 2001 From: tacherasasi Date: Wed, 25 Jun 2025 08:48:07 +0300 Subject: [PATCH 2/4] Add support for AMPERSAND and POINTER token types in lexer and parser --- lexer/lexer.go | 2 ++ object/object.go | 1 + object/pointer.go | 21 +++++++++++++++++++++ parser/parser.go | 2 ++ 4 files changed, 26 insertions(+) create mode 100644 object/pointer.go diff --git a/lexer/lexer.go b/lexer/lexer.go index 7d83728..7442517 100644 --- a/lexer/lexer.go +++ b/lexer/lexer.go @@ -153,6 +153,8 @@ func (l *Lexer) NextToken() token.Token { ch := l.ch l.readChar() tok = token.Token{Type: token.AND, Literal: string(ch) + string(l.ch), Line: l.line} + } else { + tok = newToken(token.AMPERSAND, l.line, l.ch) } case rune('|'): if l.peekChar() == rune('|') { diff --git a/object/object.go b/object/object.go index 46de338..abd5289 100644 --- a/object/object.go +++ b/object/object.go @@ -27,6 +27,7 @@ const ( BYTE_OBJ = "BYTE" PACKAGE_OBJ = "PAKEJI" INSTANCE = "PAKEJI" + POINTER_OBJ = "POINTER" AT = "@" ) diff --git a/object/pointer.go b/object/pointer.go new file mode 100644 index 0000000..0eb9bec --- /dev/null +++ b/object/pointer.go @@ -0,0 +1,21 @@ +package object + +import ( + "fmt" +) + +type Pointer struct { + Ref Object +} + +func (p *Pointer) Type() ObjectType { + return POINTER_OBJ +} + +func (p *Pointer) Inspect() string { + if p.Ref == nil { + return "Pointer(addr=nil, value=nil)" + } + return fmt.Sprintf("Pointer(addr=%p, value=%s)", p.Ref, p.Ref.Inspect()) +} + diff --git a/parser/parser.go b/parser/parser.go index 0bcf5f8..f65a023 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -113,6 +113,8 @@ func New(l *lexer.Lexer) *Parser { p.registerPrefix(token.IMPORT, p.parseImport) p.registerPrefix(token.PACKAGE, p.parsePackage) p.registerPrefix(token.AT, p.parseAt) + p.registerPrefix(token.AMPERSAND, p.parsePrefixExpression) + p.registerPrefix(token.ASTERISK, p.parsePrefixExpression) p.infixParseFns = make(map[token.TokenType]infixParseFn) p.registerInfix(token.AND, p.parseInfixExpression) From 7ecce74abc1aa19b4ea4ff7e3c911804578c6b15 Mon Sep 17 00:00:00 2001 From: tacherasasi Date: Wed, 25 Jun 2025 08:48:07 +0300 Subject: [PATCH 3/4] Remove unnecessary blank line in Pointer's Inspect method --- examples/pointer.nr | 5 +++++ object/pointer.go | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 examples/pointer.nr diff --git a/examples/pointer.nr b/examples/pointer.nr new file mode 100644 index 0000000..85f942f --- /dev/null +++ b/examples/pointer.nr @@ -0,0 +1,5 @@ +fanya x = 42 * 2 +fanya p = &x +andika(p) +andika("POINTER is",p) +andika("VALUE is",*p) \ No newline at end of file diff --git a/object/pointer.go b/object/pointer.go index 0eb9bec..e6dfda8 100644 --- a/object/pointer.go +++ b/object/pointer.go @@ -18,4 +18,3 @@ func (p *Pointer) Inspect() string { } return fmt.Sprintf("Pointer(addr=%p, value=%s)", p.Ref, p.Ref.Inspect()) } - From a224ba9f386ce262f4991b4a79cbdaf4dfa1533c Mon Sep 17 00:00:00 2001 From: tacherasasi Date: Wed, 25 Jun 2025 08:48:07 +0300 Subject: [PATCH 4/4] Add pointer support with Swahili messages and pointer object implementation --- evaluator/prefix.go | 8 ++++---- object/pointer.go | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/evaluator/prefix.go b/evaluator/prefix.go index 752319f..c2d03af 100644 --- a/evaluator/prefix.go +++ b/evaluator/prefix.go @@ -39,18 +39,18 @@ func evalPrefixExpression(operator string, right object.Object, line int) object return evalPlusPrefixOperatorExpression(right, line) case "*": if right == nil { - return newError("Line %d: cannot dereference nil", line) + return newError("Mstari %d: huwezi kufikia thamani ya pointer isiyo na kitu (nil)", line) } if p, ok := right.(*object.Pointer); ok { if p.Ref == nil { - return newError("Line %d: pointer is nil", line) + return newError("Mstari %d: pointer haina kitu (nil)", line) } return p.Ref } - return newError("Line %d: cannot dereference non-pointer", line) + return newError("Mstari %d: huwezi kufikia thamani ya kitu ambacho si pointer", line) case "&": if right == nil { - return newError("Line %d: cannot take address of nil", line) + return newError("Mstari %d: huwezi kupata anwani ya kitu kisicho na thamani (nil)", line) } return &object.Pointer{Ref: right} default: diff --git a/object/pointer.go b/object/pointer.go index e6dfda8..263375f 100644 --- a/object/pointer.go +++ b/object/pointer.go @@ -14,7 +14,7 @@ func (p *Pointer) Type() ObjectType { func (p *Pointer) Inspect() string { if p.Ref == nil { - return "Pointer(addr=nil, value=nil)" + return "Pointer(anwani=nil, thamani=nil)" } - return fmt.Sprintf("Pointer(addr=%p, value=%s)", p.Ref, p.Ref.Inspect()) + return fmt.Sprintf("Pointer(anwani=%p, thamani=%s)", p.Ref, p.Ref.Inspect()) }