Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
bin
doc/repl/glj.wasm
.direnv

# useful to symlink in for context
clojure
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ gocmd:
.PHONY: generate
generate:
@go generate ./...
@echo "(map compile '[glojure.core glojure.core.async glojure.walk glojure.template])" | \
GLOJURE_STDLIB_PATH=./pkg/stdlib $(GO_CMD) run ./cmd/glj

.PHONY: build
build: $(GLJ)
Expand All @@ -70,7 +72,7 @@ pkg/stdlib/glojure/%.glj: scripts/rewrite-core/originals/%.clj scripts/rewrite-c
@mkdir -p $(dir $@)
@scripts/rewrite-core/run.sh $< > $@

bin/%/glj: $(wildcard ./cmd/glj/*.go) $(wildcard ./pkg/**/*.go) $(wildcard ./internal/**/*.go)
bin/%/glj: generate $(wildcard ./cmd/glj/*.go) $(wildcard ./pkg/**/*.go) $(wildcard ./internal/**/*.go)
@echo "Building $@"
@mkdir -p $(dir $@)
@scripts/build-glj.sh $@ $*
Expand All @@ -89,7 +91,7 @@ $(TEST_TARGETS): gocmd $(GLJ)
@$(GO_CMD) run ./cmd/glj/main.go $(basename $@)

.PHONY: test
test: vet $(TEST_TARGETS)
test: $(TEST_TARGETS) # vet - vet is disabled until we fix errors in generated code

.PHONY: format
format:
Expand Down
1 change: 1 addition & 0 deletions cmd/gen-import-interop/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ var defaultPackages = []string{
"crypto/x509",
"crypto/x509/pkix",
"database/sql",
"github.com/google/uuid",
"database/sql/driver",
"debug/buildinfo",
"debug/dwarf",
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go4.org/unsafe/assume-no-moving-gc v0.0.0-20230525183740-e7c30c78aeb2 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
Expand Down
90 changes: 85 additions & 5 deletions pkg/gen/gljimports/gljimports_darwin_amd64.go

Large diffs are not rendered by default.

90 changes: 85 additions & 5 deletions pkg/gen/gljimports/gljimports_darwin_arm64.go

Large diffs are not rendered by default.

90 changes: 85 additions & 5 deletions pkg/gen/gljimports/gljimports_js_wasm.go

Large diffs are not rendered by default.

90 changes: 85 additions & 5 deletions pkg/gen/gljimports/gljimports_linux_amd64.go

Large diffs are not rendered by default.

90 changes: 85 additions & 5 deletions pkg/gen/gljimports/gljimports_linux_arm64.go

Large diffs are not rendered by default.

90 changes: 85 additions & 5 deletions pkg/gen/gljimports/gljimports_windows_amd64.go

Large diffs are not rendered by default.

90 changes: 85 additions & 5 deletions pkg/gen/gljimports/gljimports_windows_arm.go

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions pkg/gljmain/gljmain.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import (
// bootstrap the runtime
_ "github.com/glojurelang/glojure/pkg/glj"

_ "github.com/glojurelang/glojure/pkg/stdlib/glojure/core"
_ "github.com/glojurelang/glojure/pkg/stdlib/glojure/core/async"
_ "github.com/glojurelang/glojure/pkg/stdlib/glojure/protocols"

"github.com/glojurelang/glojure/pkg/lang"
"github.com/glojurelang/glojure/pkg/reader"
"github.com/glojurelang/glojure/pkg/repl"
Expand Down
30 changes: 30 additions & 0 deletions pkg/lang/arraylist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package lang

// ArrayList is a minimal implementation of a subset of Java's
// ArrayList to replace uses of java.util.ArrayList in the Clojure
// standard library.
type ArrayList struct {
data []any
}

func NewArrayList(items []any) *ArrayList {
return &ArrayList{
data: items,
}
}

func (al *ArrayList) Add(item any) {
al.data = append(al.data, item)
}

func (al *ArrayList) Clear() {
al.data = []any{}
}

func (al *ArrayList) IsEmpty() bool {
return len(al.data) == 0
}

func (al *ArrayList) ToArray() []any {
return al.data
}
19 changes: 18 additions & 1 deletion pkg/lang/atom.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import "sync/atomic"
type (
Atom struct {
state atomic.Value

meta IPersistentMap
}
)

Expand All @@ -13,12 +15,20 @@ var (
_ IRef = (*Atom)(nil)
)

func NewAtom(val interface{}) *Atom {
func NewAtom(val any) *Atom {
a := &Atom{}
a.state.Store(Box{val})
return a
}

func NewAtomWithMeta(val any, meta IPersistentMap) *Atom {
a := NewAtom(val)
if meta != nil {
a.meta = meta
}
return a
}

func (a *Atom) Deref() interface{} {
return a.state.Load().(Box).val
}
Expand Down Expand Up @@ -53,3 +63,10 @@ func (a *Atom) Reset(newVal interface{}) interface{} {
// TODO: notifyWatches
return newVal
}

func (a *Atom) Meta() IPersistentMap {
if a.meta == nil {
return nil
}
return a.meta
}
10 changes: 10 additions & 0 deletions pkg/lang/bigdecimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,21 @@ func NewBigDecimalFromInt64(x int64) *BigDecimal {
return &BigDecimal{val: new(big.Float).SetInt64(x)}
}

func NewBigDecimalFromRatio(x *Ratio) *BigDecimal {
return &BigDecimal{val: new(big.Float).SetRat(x.val)}
}

func (n *BigDecimal) ToBigInteger() *big.Int {
res, _ := n.val.Int(nil)
return res
}

func (n *BigDecimal) ToBigFloat() *big.Float {
res := new(big.Float)
res.Set(n.val)
return res
}

func (n *BigDecimal) String() string {
return n.val.String()
}
Expand Down
30 changes: 30 additions & 0 deletions pkg/lang/catch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package lang

import (
"errors"
"reflect"
)

var (
errorType = reflect.TypeOf((*error)(nil)).Elem()
)

// CatchMatches checks if a recovered panic value matches an expected catch type.
// This implements the semantics of Clojure's try/catch matching.
func CatchMatches(r, expect any) bool {
if IsNil(expect) {
return false
}

// if expect is an error type, check if r is an instance of it
if rErr, ok := r.(error); ok {
if expectTyp, ok := expect.(reflect.Type); ok && expectTyp.Implements(errorType) {
expectVal := reflect.New(expectTyp).Elem().Interface().(error)
if errors.Is(rErr, expectVal) {
return true
}
}
}

return reflect.TypeOf(r).AssignableTo(expect.(reflect.Type))
}
4 changes: 4 additions & 0 deletions pkg/lang/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ type (
Context() context.Context

Errorf(form interface{}, format string, args ...interface{}) error

// LookupLocal looks up a local binding in the environment.
// This is used by the codegen system to access captured values.
LookupLocal(name string) (any, bool)
}

// RecurError is an error returned by a recur form.
Expand Down
85 changes: 76 additions & 9 deletions pkg/lang/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import (
)

type (
Error struct {
msg string
}

TimeoutError struct {
msg string
}
Expand All @@ -21,17 +25,28 @@ type (
msg string
}

UnsupportedOperationError struct {
msg string
}

ArithmeticError struct {
msg string
}

CompilerError struct {
file string
line int
col int
err error
}

// Stacker is an interface for retrieving stack traces.
Stacker interface {
Stack() []StackFrame
}

// Error is a value that represents an error.
Error struct {
// EvalError is a value that represents an evaluation error.
EvalError struct {
err error
stack []StackFrame
}
Expand All @@ -44,6 +59,20 @@ type (
}
)

////////////////////////////////////////////////////////////////////////////////

// NewError creates a new error value.
func NewError(msg string) error {
return &Error{msg: msg}
}

// Error returns the error message.
func (e *Error) Error() string {
return e.msg
}

////////////////////////////////////////////////////////////////////////////////

// NewTimeoutError creates a new timeout error.
func NewTimeoutError(msg string) error {
return &TimeoutError{msg: msg}
Expand All @@ -59,6 +88,8 @@ func (e *TimeoutError) Is(other error) bool {
return ok
}

////////////////////////////////////////////////////////////////////////////////

func NewIndexOutOfBoundsError() error {
return &IndexOutOfBoundsError{}
}
Expand All @@ -72,6 +103,8 @@ func (e *IndexOutOfBoundsError) Is(other error) bool {
return ok
}

////////////////////////////////////////////////////////////////////////////////

func NewIllegalArgumentError(msg string) error {
return &IllegalArgumentError{msg: msg}
}
Expand All @@ -85,6 +118,23 @@ func (e *IllegalArgumentError) Is(other error) bool {
return ok
}

////////////////////////////////////////////////////////////////////////////////

func NewUnsupportedOperationError(msg string) error {
return &UnsupportedOperationError{msg: msg}
}

func (e *UnsupportedOperationError) Error() string {
return e.msg
}

func (e *UnsupportedOperationError) Is(other error) bool {
_, ok := other.(*UnsupportedOperationError)
return ok
}

////////////////////////////////////////////////////////////////////////////////

func NewArithmeticError(msg string) error {
return &ArithmeticError{msg: msg}
}
Expand All @@ -98,6 +148,8 @@ func (e *ArithmeticError) Is(other error) bool {
return ok
}

////////////////////////////////////////////////////////////////////////////////

func NewIllegalStateError(msg string) error {
return &IllegalStateError{msg: msg}
}
Expand All @@ -111,19 +163,34 @@ func (e *IllegalStateError) Is(other error) bool {
return ok
}

////////////////////////////////////////////////////////////////////////////////

func NewCompilerError(file string, line, col int, err error) error {
return &CompilerError{
file: file,
line: line,
col: col,
err: err,
}
}

func (e *CompilerError) Error() string {
return fmt.Sprintf("compiler error at %s:%d:%d: %v", e.file, e.line, e.col, e.err)
}

////////////////////////////////////////////////////////////////////////////////
// TODO: Revisit

// NewError creates a new error value.
func NewError(frame StackFrame, err error) *Error {
return &Error{
// NewEvalError creates a new error value.
func NewEvalError(frame StackFrame, err error) *EvalError {
return &EvalError{
err: err,
stack: []StackFrame{frame},
}
}

// Error returns the error message.
func (e *Error) Error() string {
func (e *EvalError) Error() string {
var builder strings.Builder
builder.WriteString(e.err.Error())
builder.WriteString("\nStack trace (most recent call first):\n")
Expand All @@ -145,17 +212,17 @@ func (e *Error) Error() string {
}

// Stack returns the stack trace.
func (e *Error) Stack() []StackFrame {
func (e *EvalError) Stack() []StackFrame {
return e.stack
}

// AddStack adds a new stack trace entry.
func (e *Error) AddStack(frame StackFrame) error {
func (e *EvalError) AddStack(frame StackFrame) error {
e.stack = append(e.stack, frame)
return e
}

// Unwrap returns the underlying error.
func (e *Error) Unwrap() error {
func (e *EvalError) Unwrap() error {
return e.err
}
3 changes: 3 additions & 0 deletions pkg/lang/functional.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ func ReduceInit(f func(interface{}, interface{}) interface{}, init interface{},
var res interface{} = init
for ; seq != nil; seq = seq.Next() {
res = f(res, seq.First())
if IsReduced(res) {
return res.(IDeref).Deref()
}
}
return res
}
Expand Down
Loading