Last active
January 11, 2021 20:45
-
-
Save ExFed/ee4f589cd43c3d7bcc952b88c12b7b46 to your computer and use it in GitHub Desktop.
gStruct Binding PoC
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import groovy.transform.Canonical | |
import groovy.transform.CompileStatic | |
interface Type {} | |
@CompileStatic | |
@Canonical | |
class Ref implements Type { | |
String name | |
Type type | |
String toString() { name } | |
} | |
@CompileStatic | |
@Canonical | |
class Extern implements Type { | |
String name | |
} | |
@CompileStatic | |
@Canonical | |
class Tuple implements Type { | |
List<Type> types = [] | |
String toString() { "Tuple(${types.join(', ')})" } | |
} | |
@CompileStatic | |
@Canonical | |
class Struct implements Type { | |
Map<String, Type> fields = [:] | |
String toString() { "Struct(${fields.collect { k, v -> "$k:$v" }.join(', ')})" } | |
} | |
class Compiler { | |
@CompileStatic | |
static Closure<?> binder(Map<String, Type> bindings) { | |
return { Map<String, Type> mapping -> | |
def dupes = mapping.keySet().intersect(bindings.keySet()) | |
if (dupes) { | |
throw new RuntimeException("duplicate names: $dupes") | |
} | |
println "## binding $mapping" | |
bindings << mapping | |
} | |
} | |
static Map<String, Type> compile(Closure code) { | |
def model = new TreeMap<String, Type>().withDefault { String name -> | |
{ -> throw new RuntimeException("name not found in model: $name") }.call() | |
} | |
def getRefs = { -> model.collectEntries { k, v -> [k, new Ref(k, v)] } } | |
def tasks = [] as Queue<Closure> // breadth first syntax traversal | |
def addTask = { Closure task -> tasks.offer(task) } | |
def nextTask = { -> tasks.poll() } | |
def scope = new Expando().tap { | |
bind = binder(model) | |
extern = { String name -> new Extern(name) } | |
tuple = { Closure cl -> | |
println '# initializing tuple' | |
def tuple = new Tuple() | |
addTask { | |
println '# constructing tuple' | |
(getRefs() as Expando).tap { | |
types = { Type... types -> | |
println "## adding types: $types" | |
tuple.types.addAll(types) | |
} | |
}.with cl // apply cl in context of tuple scope | |
} | |
return tuple | |
} | |
struct = { Closure cl -> | |
println '# initializing struct' | |
def struct = new Struct() | |
addTask { | |
println '# constructing struct' | |
(getRefs() as Expando).tap { | |
field = binder(struct.fields) | |
}.with cl // apply cl in context of struct scope | |
} | |
return struct | |
} | |
} | |
addTask { scope.with code } // get the traversal started | |
while (tasks) { | |
nextTask().call() // traverse each syntax node | |
} | |
return model | |
} | |
} | |
Compiler.compile { | |
bind LatLon: struct { | |
field latitude: DecimalDeg | |
field longitude: DegMinSec | |
} | |
bind GeoVolume: struct { | |
field northEast: LatLon | |
field southWest: LatLon | |
field height: Real | |
} | |
bind DegMinSec: tuple { types Int, Int, Real } | |
bind DecimalDeg: tuple { types extern('double') } | |
bind Int: extern('int') | |
bind Real: extern('float') | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment