init commit

This commit is contained in:
Adam Jeniski 2025-11-01 15:01:22 -09:00
commit 143b17a6c1
8 changed files with 315 additions and 0 deletions

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module mal-go
go 1.24.2

70
hash_map/hash_map.go Normal file
View File

@ -0,0 +1,70 @@
package hash_map
import (
"mal-go/utils"
"maps"
"strings"
)
// TODO: replace COW with proper HashArrayMappedTrie impelmentation of PersistentHashMap
type HashMap struct {
_map map[any]any
}
func New() *HashMap {
return new(HashMap).Init()
}
func Init(this *HashMap) *HashMap {
this._map = make(map[any]any)
return this
}
func (this *HashMap) Init() *HashMap {
return Init(this)
}
func Clone(this *HashMap) *HashMap {
if this == nil {
return nil
}
newMap := New().Init()
maps.Copy(newMap._map, this._map)
return newMap
}
func (this *HashMap) Clone() *HashMap {
return Clone(this)
}
func Conj(this *HashMap, key any, val any) *HashMap {
newMap := this.Clone()
newMap._map[key] = val
return newMap
}
func (this *HashMap) Conj(key any, val any) *HashMap {
return Conj(this, key, val)
}
func String(this *HashMap) string {
if this == nil {
return "{}"
}
var sb strings.Builder
sb.WriteRune('{')
for key, val := range this._map {
sb.WriteString(utils.Stringify(key))
sb.WriteRune(' ')
sb.WriteString(utils.Stringify(val))
sb.WriteRune(',')
sb.WriteRune(' ')
}
return sb.String()[:sb.Len()-2] + "}"
}
func (this *HashMap) String() string {
return String(this)
}

40
keyword/keyword.go Normal file
View File

@ -0,0 +1,40 @@
package keyword
var intern_map map[string]*Keyword
type Keyword struct {
ns string
keyword string
}
func Intern(keyword string) *Keyword {
return Intern_ns("", keyword)
}
func Intern_ns(ns string, keyword string) *Keyword {
combined_str := ns + "/" + keyword
existingkeyword, ok := intern_map[combined_str]
if ok {
return existingkeyword
} else {
newkeyword := new(Keyword)
newkeyword.ns = ns
newkeyword.keyword = keyword
if intern_map == nil {
intern_map = make(map[string]*Keyword)
}
intern_map[combined_str] = newkeyword
return newkeyword
}
}
func String(this *Keyword) string {
if this.ns == "" {
return ":" + this.keyword
}
return ":" + this.ns + "/" + this.keyword
}
func (this *Keyword) String() string {
return String(this)
}

72
list/list.go Normal file
View File

@ -0,0 +1,72 @@
package list
import (
"fmt"
"strings"
)
type List struct {
Value any
next *List
}
func New(val any) *List {
return new(List).Init(val)
}
func (this *List) Init(val any) *List {
return Init(this, val)
}
func Init(this *List, val any) *List {
this.Value = val
this.next = nil
return this
}
func (this *List) Conj(val any) *List {
return Conj(this, val)
}
func Conj(this *List, val any) *List {
new_head := New(val)
new_head.next = this
return new_head
}
func Rest(this *List) *List {
if this == nil {
return nil
}
return this.next
}
func (this *List) Rest() *List {
return Rest(this)
}
func First(this *List) any {
return this.Value
}
func (this *List) First() any {
return First(this)
}
func String(this *List) string {
if this == nil {
return "{}"
}
var sb strings.Builder
sb.WriteRune('(')
// Iterate and print elements
for e := this; e != nil; e = Rest(e) {
sb.WriteString(fmt.Sprint(e.Value))
sb.WriteRune(' ')
}
return sb.String()[:sb.Len()-1] + ")"
}
func (this *List) String() string {
return String(this)
}

31
main.go Normal file
View File

@ -0,0 +1,31 @@
package main
import (
"fmt"
"mal-go/hash_map"
"mal-go/keyword"
"mal-go/list"
"mal-go/symbol"
"mal-go/vector"
)
func main() {
myList := list.New(5)
myList = myList.Conj(6)
plus := symbol.Intern("clojure.core", "+")
myList = myList.Conj(plus)
fmt.Println(myList)
baz := keyword.Intern("baz")
myMap := hash_map.New()
myMap = myMap.Conj("foo", "bar")
myMap = myMap.Conj(baz, 42)
myMap = myMap.Conj("fizz", "buzz")
fmt.Println(myMap)
myVec := vector.New()
myVec = myVec.Conj(plus)
myVec = myVec.Conj(1)
myVec = myVec.Conj(2)
fmt.Println(myVec)
}

36
symbol/symbol.go Normal file
View File

@ -0,0 +1,36 @@
package symbol
var intern_map map[string]*Symbol
type Symbol struct {
ns string
symbol string
}
func Intern(ns string, symbol string) *Symbol {
combined_str := ns + "/" + symbol
existingSymbol, ok := intern_map[combined_str]
if ok {
return existingSymbol
} else {
newSymbol := new(Symbol)
newSymbol.ns = ns
newSymbol.symbol = symbol
if intern_map == nil {
intern_map = make(map[string]*Symbol)
}
intern_map[combined_str] = newSymbol
return newSymbol
}
}
func String(this *Symbol) string {
if this.ns == "" {
return this.symbol
}
return this.ns + "/" + this.symbol
}
func (this *Symbol) String() string {
return String(this)
}

12
utils/utils.go Normal file
View File

@ -0,0 +1,12 @@
package utils
import "fmt"
func Stringify(value any) string {
switch value.(type) {
case string:
return fmt.Sprintf("\"%s\"", value)
default:
return fmt.Sprint(value)
}
}

51
vector/vector.go Normal file
View File

@ -0,0 +1,51 @@
package vector
import (
"mal-go/utils"
"strings"
)
// TODO: replace COW with proper HashArrayMappedTrie impelmentation of PersistentVector
type Vector struct {
_slice []any
}
func New() *Vector {
return new(Vector).Init()
}
func (this *Vector) Init() *Vector {
this._slice = make([]any, 0)
return this
}
func Conj(this *Vector, data any) *Vector {
newVec := New()
for _, el := range this._slice {
newVec._slice = append(newVec._slice, el)
}
newVec._slice = append(newVec._slice, data)
return newVec
}
func (this *Vector) Conj(data any) *Vector {
return Conj(this, data)
}
func String(this *Vector) string {
if this == nil {
return "[]"
}
var sb strings.Builder
sb.WriteRune('[')
for _, el := range this._slice {
sb.WriteString(utils.Stringify(el))
sb.WriteRune(' ')
}
return sb.String()[:sb.Len()-1] + "]"
}
func (this *Vector) String() string {
return String(this)
}