Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Context for vars #7

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
35 changes: 25 additions & 10 deletions lang/Compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package lang
import (
"io"
"math/rand"
"golang.org/x/net/context"
)

const (
Expand Down Expand Up @@ -50,10 +51,18 @@ var loadNs *Symbol = InternSymbolByNsname("load-ns")
var inlineKey *Symbol = InternSymbolByNsname("inline")
// TODO: more declarations here...


var KEYWORDS *Var = CreateVarFromNothing().SetDynamic()
var COMPILE_PATH *Var = InternVar(FindOrCreateNamespace(InternSymbolByNsname("clojure.core")),
InternSymbolByNsname("*compile-path*"), nil).SetDynamic()

type ObjExpr struct {
name string
internalName string
thisName string
keywords IPersistentMap
constants *PersistentVector
}

/*
Compiler struct and methods
*/
Expand All @@ -62,8 +71,10 @@ type compiler struct{}

var Compiler = &compiler{}

// TODO
func (_ *compiler) CurrentNS() *Namespace {
return CURRENT_NS.Deref().(*Namespace)
panic(NotYetImplementedException)
// return CURRENT_NS.Deref().(*Namespace)
}

func (_ *compiler) NamespaceFor(inns *Namespace, sym *Symbol) *Namespace {
Expand All @@ -90,9 +101,11 @@ func (_ *compiler) Macroexpand(form interface{}) interface{} {
func (_ *compiler) Compile(rdr *io.Reader, sourcePath string, sourceName string) interface{} {
// TODO: Do we need this? I don't know.
// #VESTIGIAL
/*
if COMPILE_PATH.Deref() == nil {
panic("*compile-path* not set")
}
*/

var EOF int = rand.Int() // TODO: Sentinel value
var ret interface{}
Expand All @@ -105,31 +118,33 @@ func (_ *compiler) Compile(rdr *io.Reader, sourcePath string, sourceName string)
}

// In JVM Clojure, gen is a GeneratorAdapter. We don't have an analog for that here.
func (_ *compiler) Compile1(gen interface{}, objx ObjExpr, form interface{}) {
func (_ *compiler) Compile1(ctx context.Context, gen interface{}, objx ObjExpr, form interface{}) {
// TODO: some initial set-up.

// try, catch (might want better error handling here)
ctx =
// try block begins here
form = Compiler.Macroexpand(form)
switch f := form.(type) {
case ISeq:
if Util.Equals(RT.First(form), DO) {
for s := RT.Next(form); s != nil; s = RT.Next(s) {
Compiler.Compile1(gen, objx, RT.First(s))
Compiler.Compile1(ctx, gen, objx, RT.First(s))
}
}
default:
expr := Compiler.Analyze(EVAL, form)
objx.keywords = KEYWORDS.Deref()
objx.vars = VAR.Deref()
objx.constants = CONSTANTS.Deref()
objx.keywords = KEYWORDS.Deref().(IPersistentMap)
objx.vars = VAR.Deref().(IPersistentMap)
objx.constants = CONSTANTS.Deref().(*PersistentVector)
expr.Emit(EXPRESSION, objx, gen)
expr.Eval()
}
// TODO: Var.Pop thread bindings
}

func (_ *compiler) Eval(form interface{}, freshLoader bool) interface{} {
createdLoader := false // do we need this?
}


func (_ *compiler) Analyze(a interface{}, b interface{}) interface{} {
panic(NotYetImplementedException)
}
134 changes: 68 additions & 66 deletions lang/Var.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@ package lang

import (
"bytes"
"sync"

"golang.org/x/net/context"
)

/*
Assorted class variables


*/

// TODO: I found this really useful: http://www.golangbootcamp.com/book/concurrency
Expand All @@ -26,18 +23,30 @@ var rev int = 0 // maybe atomic integer since this will be shared.
/*
Var

Extends: ARef

Implements: IFn, IRef, Settable

Notes: in JVM Clojure, the implementation of Vars is heavily dependent on the JVM's support
for thread-local storage. In the almost total absence of a simple analog here in Go, I've
chosen to instead use the x/net/context package instead as a way of passing explicit
bindings.
*/

type Var struct {
ARef

// AReference
_meta IPersistentMap

// ARef
validator IFn
watches *PersistentHashMap // default EMPTY

rev int
privateMeta IPersistentMap
root interface{}
dyanmic bool
threadBound bool // atomicboolean TODO
dynamic bool
sym *Symbol
ns *Namespace
}
Expand All @@ -63,15 +72,15 @@ func (v *Var) String() string {

func (v *Var) SetDynamic(args ...bool) *Var {
if len(args) == 0 {
v.dyanmic = true
v.dynamic = true
} else {
v.dyanmic = args[0]
v.dynamic = args[0]
}
return v
}

func (v *Var) IsDynamic() bool {
return v.IsDynamic()
return v.dynamic
}

func InternVar(ns *Namespace, sym *Symbol, root interface{}) *Var {
Expand Down Expand Up @@ -112,7 +121,6 @@ func CreateVarFromNothing() *Var {
return &Var{
ns: nil,
sym: nil,
threadBound: false, // TODOAtomicBoolean
root: VarUnbound{
v: v,
},
Expand All @@ -127,23 +135,53 @@ func CreateVarFromRoot(root interface{}) *Var {
}
}

func (v *Var) isBound() bool {
// TODO
panic(NotYetImplementedException)
// unexported type and key for var context utility functions
type key int
var varKey key = 0

// Set the new Var root for the provided context
func setVarBindingForContext(ctx context.Context, val interface{}) context.Context {
return context.WithValue(ctx, varKey, val)
}

// TODO
func (v *Var) Get() interface{} {
panic(NotYetImplementedException)
// Retrieve the new Var root from the provided context
func getVarBindingFromContext(ctx context.Context) (*Frame, bool) {
r, ok := ctx.Value(varKey).(*Frame)
return r, ok
}

// TODO: this is a naive and stupid implementation
func (v *Var) Deref() interface{} {
func (v *Var) isBound(ctx context.Context) bool {
r, ok := getVarBindingFromContext(ctx)
if ok == false {
panic("Stored var value wasn't an instance of *lang.Frame")
}
return v.HasRoot() || r != nil && r.bindings.ContainsKey(v)
}

func (v *Var) Get(ctx context.Context) interface{} {
r, ok := getVarBindingFromContext(ctx)
if ok == false {
panic("Stored var value wasn't an instance of *lang.Frame")
}
if r == nil {
return v.root
}
return v.Deref(ctx)
}

func (v *Var) Deref(ctx context.Context) interface{} {
r, ok := getVarBindingFromContext(ctx)
if (r != nil) {
return r.bindings.EntryAt(v)
}
return v.root
}

// TODO
func (v *Var) SetValidator(vf IFn) {
if v.HasRoot() {
v.validate()
}
panic(NotYetImplementedException)
}

Expand Down Expand Up @@ -213,35 +251,26 @@ func (v *Var) BindRoot(root interface{}) {
v.root = root
}

func (v *Var) Fn() IFn {
return v.Deref().(IFn)
func (v *Var) Fn(ctx context.Context) IFn {
return v.Deref(ctx).(IFn)
}

func (v *Var) Call() interface{} {
return v.Invoke()
func (v *Var) Call(ctx context.Context) interface{} {
return v.Invoke(ctx)
}

func (v *Var) Run() {
v.Invoke()
func (v *Var) Run(ctx context.Context) {
v.Invoke(ctx)
}

func (v *Var) Invoke(args ...interface{}) interface{} {
return v.Fn().Invoke(args...)
func (v *Var) Invoke(ctx context.Context, args ...interface{}) interface{} {
return v.Fn(ctx).Invoke(args...)
}

func (v *Var) ApplyTo(arglist ISeq) interface{} {
return AFn_ApplyToHelper(v, arglist)
}

/*
VarTBox [TBox]
*/

type VarTBox struct {
val interface{}
lock *sync.Mutex // instead of keeping track of thread
}

/*
VarUnbound [Unbound]
*/
Expand Down Expand Up @@ -284,36 +313,9 @@ func (f *Frame) Clone() interface{} {
}
}

/*
VarFrameDvals

This class is just a ThreadLocal<Frame> in JVM Clojure with an initialValue() func.
*/

type VarFrameDvals struct {
Frame

lock *sync.Mutex
}

func (d *VarFrameDvals) InitialValue() *Frame {
return TOP_FRAME
}

// TODO
func getThreadBindingFrame() interface{} {
return nil
}

// TODO
func cloneThreadBindingFrame() interface{} {
return nil
}

// TODO
func resetThreadBindingFrame() interface{} {
return nil
}
// In JVM Clojure, dvals is a ThreadLocal<Frame>. Here we pass it around in a context.
// First we initialize dvals to TOP_FRAME
var dvals *Frame = TOP_FRAME

// TODO...still most of this file.

Expand All @@ -326,4 +328,4 @@ var assoc = &assocAnon{}
func (a *assocAnon) Invoke(args ...interface{}) interface{} {
m, k, v := args[0], args[1], args[2]
return RT.Assoc(m, k, v)
}
}