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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ vet:

.PHONY: $(TEST_TARGETS)
$(TEST_TARGETS): gocmd $(GLJ)
@$(GO_CMD) run ./cmd/glj/main.go $(basename $@)
@$(GLJ) $(basename $@)

.PHONY: test
test: $(TEST_TARGETS) # vet - vet is disabled until we fix errors in generated code
Expand Down
23 changes: 15 additions & 8 deletions pkg/ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,21 @@ type (
}

CaseNode struct {
Test *Node
Nodes []*Node
Default *Node
}

CaseNodeNode struct {
Tests []*Node
Then *Node
Test *Node // The expression to test
Shift int64 // Bit shift for hash compaction
Mask int64 // Bit mask for hash compaction
TestType interface{} // Keyword: :int, :hash-identity, or :hash-equiv
SwitchType interface{} // Keyword: :compact or :sparse
Default *Node // Default expression
Entries []CaseEntry // Case entries
SkipCheck map[int64]bool // Set of keys with collisions
}

CaseEntry struct {
Key int64 // Map key (int value or shifted/masked hash)
TestConstant *Node // Original test constant (nil for collisions)
ResultExpr *Node // Result expression or condp for collisions
HasCollision bool // Whether this is a collision case
}

TheVarNode struct {
Expand Down
86 changes: 65 additions & 21 deletions pkg/compiler/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -1393,7 +1393,7 @@ func (a *Analyzer) parseCaseStar(form interface{}, env Env) (*ast.Node, error) {
return nil, exInfo(fmt.Sprintf("case*: %v", err), nil)
}
if switchType != KWCompact && switchType != KWSparse {
return nil, exInfo(fmt.Sprintf("unexpected shift type: %v", switchType), nil)
return nil, exInfo(fmt.Sprintf("unexpected switch type: %v", switchType), nil)
}
if testType != KWInt && testType != KWHashIdentity && testType != KWHashEquiv {
return nil, exInfo(fmt.Sprintf("unexpected test type: %v", testType), nil)
Expand All @@ -1408,36 +1408,80 @@ func (a *Analyzer) parseCaseStar(form interface{}, env Env) (*ast.Node, error) {
return nil, err
}

var nodes []*ast.Node
// Build skip check set
skipCheckSet := make(map[int64]bool)
if !lang.IsNil(skipCheck) {
if set, ok := skipCheck.(IPersistentSet); ok {
for seq := Seq(set); seq != nil; seq = seq.Next() {
val := First(seq)
valInt := lang.AsInt64(val)
skipCheckSet[valInt] = true
}
}
}

// Process case map entries
var entries []ast.CaseEntry
for seq := Seq(caseMap); seq != nil; seq = seq.Next() {
// TODO: is the shift, mask, etc. relevant for anything but
// performance? omitting for now.
entry := First(seq).(IMapEntry).Val()
cond, then := First(entry), second(entry)
// TODO: support a vector of conditions
condExpr, err := a.analyzeConst(cond, ctxEnv(env, KWCtxExpr))
if err != nil {
return nil, err
mapEntry := First(seq).(IMapEntry)
key := mapEntry.Key()
val := mapEntry.Val()

// Convert key to int64
keyInt := lang.AsInt64(key)

// Extract the vector [test-constant result-expr]
if Count(val) != 2 {
return nil, exInfo("case* map value must be a 2-element vector", nil)
}

testConstant := First(val)
resultExpr := second(val)

// Check if this is a collision case
// In Clojure, entries whose keys are in skipCheck should be evaluated directly
// without comparison (they contain condp expressions for collision handling)
hasCollision := false

if _, isCollision := skipCheckSet[keyInt]; isCollision {
hasCollision = true
}

// Analyze the test constant and result expression
var testConstantNode *ast.Node
if !hasCollision {
// For non-collision cases, analyze the test constant
testConstantNode, err = a.analyzeConst(testConstant, ctxEnv(env, KWCtxExpr))
if err != nil {
return nil, err
}
}
thenExpr, err := a.analyzeForm(then, env)

// Analyze the result expression (or condp for collisions)
resultExprNode, err := a.analyzeForm(resultExpr, env)
if err != nil {
return nil, err
}
caseNode := ast.MakeNode(ast.OpCaseNode, form)
caseNode.Env = env
caseNode.Sub = &ast.CaseNodeNode{
Tests: []*ast.Node{condExpr},
Then: thenExpr,
}
nodes = append(nodes, caseNode)

entries = append(entries, ast.CaseEntry{
Key: keyInt,
TestConstant: testConstantNode,
ResultExpr: resultExprNode,
HasCollision: hasCollision,
})
}

n := ast.MakeNode(ast.OpCase, form)
n.Env = env
n.Sub = &ast.CaseNode{
Test: testExpr,
Nodes: nodes,
Default: defaultExpr,
Test: testExpr,
Shift: shift,
Mask: mask,
TestType: testType,
SwitchType: switchType,
Default: defaultExpr,
Entries: entries,
SkipCheck: skipCheckSet,
}
return n, nil
}
Expand Down
15 changes: 15 additions & 0 deletions pkg/gen/gljimports/gljimports_darwin_amd64.go
Original file line number Diff line number Diff line change
Expand Up @@ -3412,6 +3412,8 @@ func RegisterImports(_register func(string, interface{})) {
_register("github.com/glojurelang/glojure/pkg/lang.APersistentMap", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.APersistentMap)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.APersistentSet", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.APersistentSet)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.APersistentVector", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.APersistentVector)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.ARef", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ARef)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.AReference", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.AReference)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.ASeq", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ASeq)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.Abs", github_com_glojurelang_glojure_pkg_lang.Abs)
_register("github.com/glojurelang/glojure/pkg/lang.Add", github_com_glojurelang_glojure_pkg_lang.Add)
Expand Down Expand Up @@ -3485,6 +3487,7 @@ func RegisterImports(_register func(string, interface{})) {
_register("github.com/glojurelang/glojure/pkg/lang.ConstructPersistentStructMap", github_com_glojurelang_glojure_pkg_lang.ConstructPersistentStructMap)
_register("github.com/glojurelang/glojure/pkg/lang.Count", github_com_glojurelang_glojure_pkg_lang.Count)
_register("github.com/glojurelang/glojure/pkg/lang.Counted", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Counted)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.Counter", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Counter)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.CreateIterate", github_com_glojurelang_glojure_pkg_lang.CreateIterate)
_register("github.com/glojurelang/glojure/pkg/lang.CreateLazilyPersistentVector", github_com_glojurelang_glojure_pkg_lang.CreateLazilyPersistentVector)
_register("github.com/glojurelang/glojure/pkg/lang.CreateOwningLazilyPersistentVector", github_com_glojurelang_glojure_pkg_lang.CreateOwningLazilyPersistentVector)
Expand All @@ -3496,6 +3499,8 @@ func RegisterImports(_register func(string, interface{})) {
_register("github.com/glojurelang/glojure/pkg/lang.CreatePersistentTreeSetWithComparator", github_com_glojurelang_glojure_pkg_lang.CreatePersistentTreeSetWithComparator)
_register("github.com/glojurelang/glojure/pkg/lang.Cycle", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Cycle)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.*Cycle", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Cycle)(nil)))
_register("github.com/glojurelang/glojure/pkg/lang.Delay", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Delay)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.*Delay", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Delay)(nil)))
_register("github.com/glojurelang/glojure/pkg/lang.Dissoc", github_com_glojurelang_glojure_pkg_lang.Dissoc)
_register("github.com/glojurelang/glojure/pkg/lang.Divide", github_com_glojurelang_glojure_pkg_lang.Divide)
_register("github.com/glojurelang/glojure/pkg/lang.EmptyList", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.EmptyList)(nil)).Elem())
Expand All @@ -3512,17 +3517,22 @@ func RegisterImports(_register func(string, interface{})) {
_register("github.com/glojurelang/glojure/pkg/lang.*Error", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Error)(nil)))
_register("github.com/glojurelang/glojure/pkg/lang.EvalError", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.EvalError)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.*EvalError", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.EvalError)(nil)))
_register("github.com/glojurelang/glojure/pkg/lang.ExceptionInfo", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ExceptionInfo)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.*ExceptionInfo", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ExceptionInfo)(nil)))
_register("github.com/glojurelang/glojure/pkg/lang.FieldOrMethod", github_com_glojurelang_glojure_pkg_lang.FieldOrMethod)
_register("github.com/glojurelang/glojure/pkg/lang.FindNamespace", github_com_glojurelang_glojure_pkg_lang.FindNamespace)
_register("github.com/glojurelang/glojure/pkg/lang.FindOrCreateNamespace", github_com_glojurelang_glojure_pkg_lang.FindOrCreateNamespace)
_register("github.com/glojurelang/glojure/pkg/lang.First", github_com_glojurelang_glojure_pkg_lang.First)
_register("github.com/glojurelang/glojure/pkg/lang.FloatCast", github_com_glojurelang_glojure_pkg_lang.FloatCast)
_register("github.com/glojurelang/glojure/pkg/lang.FnFunc", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.FnFunc)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.ForceDelay", github_com_glojurelang_glojure_pkg_lang.ForceDelay)
_register("github.com/glojurelang/glojure/pkg/lang.Future", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.Future)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.GT", github_com_glojurelang_glojure_pkg_lang.GT)
_register("github.com/glojurelang/glojure/pkg/lang.Get", github_com_glojurelang_glojure_pkg_lang.Get)
_register("github.com/glojurelang/glojure/pkg/lang.GetDefault", github_com_glojurelang_glojure_pkg_lang.GetDefault)
_register("github.com/glojurelang/glojure/pkg/lang.GetExData", github_com_glojurelang_glojure_pkg_lang.GetExData)
_register("github.com/glojurelang/glojure/pkg/lang.GetPersistentStructMapAccessor", github_com_glojurelang_glojure_pkg_lang.GetPersistentStructMapAccessor)
_register("github.com/glojurelang/glojure/pkg/lang.GetThreadBindings", github_com_glojurelang_glojure_pkg_lang.GetThreadBindings)
_register("github.com/glojurelang/glojure/pkg/lang.GlobalEnv", github_com_glojurelang_glojure_pkg_lang.GlobalEnv)
_register("github.com/glojurelang/glojure/pkg/lang.GoAppend", github_com_glojurelang_glojure_pkg_lang.GoAppend)
_register("github.com/glojurelang/glojure/pkg/lang.GoCap", github_com_glojurelang_glojure_pkg_lang.GoCap)
Expand Down Expand Up @@ -3562,6 +3572,7 @@ func RegisterImports(_register func(string, interface{})) {
_register("github.com/glojurelang/glojure/pkg/lang.IDeref", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IDeref)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.IDrop", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IDrop)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.IEditableCollection", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IEditableCollection)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.IExceptionInfo", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IExceptionInfo)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.IFn", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IFn)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.IHashEq", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IHashEq)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.IKVReduce", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.IKVReduce)(nil)).Elem())
Expand All @@ -3583,6 +3594,7 @@ func RegisterImports(_register func(string, interface{})) {
_register("github.com/glojurelang/glojure/pkg/lang.ISeq", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ISeq)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.ITransientAssociative", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ITransientAssociative)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.ITransientCollection", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ITransientCollection)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.ITransientMap", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ITransientMap)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.ITransientSet", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ITransientSet)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.ITransientVector", reflect.TypeOf((*github_com_glojurelang_glojure_pkg_lang.ITransientVector)(nil)).Elem())
_register("github.com/glojurelang/glojure/pkg/lang.Identical", github_com_glojurelang_glojure_pkg_lang.Identical)
Expand Down Expand Up @@ -3796,8 +3808,11 @@ func RegisterImports(_register func(string, interface{})) {
_register("github.com/glojurelang/glojure/pkg/lang.NewCompilerError", github_com_glojurelang_glojure_pkg_lang.NewCompilerError)
_register("github.com/glojurelang/glojure/pkg/lang.NewCons", github_com_glojurelang_glojure_pkg_lang.NewCons)
_register("github.com/glojurelang/glojure/pkg/lang.NewCycle", github_com_glojurelang_glojure_pkg_lang.NewCycle)
_register("github.com/glojurelang/glojure/pkg/lang.NewDelay", github_com_glojurelang_glojure_pkg_lang.NewDelay)
_register("github.com/glojurelang/glojure/pkg/lang.NewError", github_com_glojurelang_glojure_pkg_lang.NewError)
_register("github.com/glojurelang/glojure/pkg/lang.NewEvalError", github_com_glojurelang_glojure_pkg_lang.NewEvalError)
_register("github.com/glojurelang/glojure/pkg/lang.NewExceptionInfo", github_com_glojurelang_glojure_pkg_lang.NewExceptionInfo)
_register("github.com/glojurelang/glojure/pkg/lang.NewExceptionInfoWithCause", github_com_glojurelang_glojure_pkg_lang.NewExceptionInfoWithCause)
_register("github.com/glojurelang/glojure/pkg/lang.NewFnFunc", github_com_glojurelang_glojure_pkg_lang.NewFnFunc)
_register("github.com/glojurelang/glojure/pkg/lang.NewGoMapSeq", github_com_glojurelang_glojure_pkg_lang.NewGoMapSeq)
_register("github.com/glojurelang/glojure/pkg/lang.NewIllegalArgumentError", github_com_glojurelang_glojure_pkg_lang.NewIllegalArgumentError)
Expand Down
Loading