From 77ca0d2049d54e17b0133818dd1667d8c7f4e221 Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Sat, 18 May 2019 23:20:58 -0400 Subject: Moved some of the reflection machinery to its own modules. * WIP: Implementation of completeness testing for anonymous classes.--- documentation/research/operating_system.md | 2 + .../luxc/lang/translation/jvm/procedure/host.lux | 2 +- stdlib/source/lux/target/jvm/reflection.lux | 320 ++++++++ stdlib/source/lux/target/jvm/type/lux.lux | 109 +++ .../tool/compiler/phase/extension/analysis/jvm.lux | 815 +++++++-------------- 5 files changed, 678 insertions(+), 570 deletions(-) create mode 100644 stdlib/source/lux/target/jvm/reflection.lux create mode 100644 stdlib/source/lux/target/jvm/type/lux.lux diff --git a/documentation/research/operating_system.md b/documentation/research/operating_system.md index 4997a3cb2..bc7ecaf05 100644 --- a/documentation/research/operating_system.md +++ b/documentation/research/operating_system.md @@ -106,6 +106,7 @@ 1. http://queue.acm.org/detail.cfm?id=1317400 1. The Art of Unix Programming &&& http://www.catb.org/esr/writings/taoup/html/index.html 1. https://shivambharuka.wordpress.com/2017/10/25/arrakis-the-operating-system-is-the-control-plane/ +1. [Arrakis: The Operating System is the Control Plane](https://www.usenix.org/system/files/conference/osdi14/osdi14-paper-peter_simon.pdf) 1. https://sortix.org/os-test/ 1. https://existentialtype.wordpress.com/2016/07/11/pclsring-in-semantics/ 1. Database/Operating System Co-Design &&& https://www.research-collection.ethz.ch/handle/20.500.11850/136 @@ -185,6 +186,7 @@ 1. [OS-level Attacks and Defenses: from Software to Hardware-based Exploits](http://tuprints.ulb.tu-darmstadt.de/8482/1/gens_diss.pdf) 1. [Time Protection: The Missing OS Abstraction](https://ts.data61.csiro.au/publications/csiro_full_text//Ge_YCH_19.pdf) 1. [Light-weight Contexts: An OS Abstraction for Safety and Performance](https://www.usenix.org/system/files/conference/osdi16/osdi16-litton.pdf) +1. https://natsys-lab.blogspot.com/2019/05/goodbye-fast-system-calls.html # Driver diff --git a/new-luxc/source/luxc/lang/translation/jvm/procedure/host.lux b/new-luxc/source/luxc/lang/translation/jvm/procedure/host.lux index ae54dccc7..e57101660 100644 --- a/new-luxc/source/luxc/lang/translation/jvm/procedure/host.lux +++ b/new-luxc/source/luxc/lang/translation/jvm/procedure/host.lux @@ -719,7 +719,7 @@ (phase.throw invalid-syntax-for-argument-generation []))) (def: (method-return-type description) - (-> Text (Operation (Maybe Type))) + (-> Text (Operation Return)) (case description (^ (static jvm.void-descriptor)) (phase@wrap #.None) diff --git a/stdlib/source/lux/target/jvm/reflection.lux b/stdlib/source/lux/target/jvm/reflection.lux new file mode 100644 index 000000000..e65b6061f --- /dev/null +++ b/stdlib/source/lux/target/jvm/reflection.lux @@ -0,0 +1,320 @@ +(.module: + [lux (#- type) + ["." host (#+ import:)] + [abstract + ["." monad (#+ do)]] + [control + ["." exception (#+ exception:)] + [parser + ["" text]]] + [data + ["." error (#+ Error)] + ["." text ("#@." equivalence) + format] + [collection + ["." list ("#@." fold functor)] + ["." array] + ["." dictionary]]]] + [// + ["/" type + ["#." lux (#+ Mapping)] + ["." reflection]]]) + +(import: #long java/lang/String) + +(import: #long java/lang/Object + (toString [] java/lang/String)) + +(import: #long java/lang/reflect/Type + (getTypeName [] java/lang/String)) + +(import: #long java/lang/reflect/GenericArrayType + (getGenericComponentType [] java/lang/reflect/Type)) + +(import: #long java/lang/reflect/ParameterizedType + (getRawType [] java/lang/reflect/Type) + (getActualTypeArguments [] (Array java/lang/reflect/Type))) + +(import: #long (java/lang/reflect/TypeVariable d) + (getName [] java/lang/String) + (getBounds [] (Array java/lang/reflect/Type))) + +(import: #long (java/lang/reflect/WildcardType d) + (getLowerBounds [] (Array java/lang/reflect/Type)) + (getUpperBounds [] (Array java/lang/reflect/Type))) + +(import: #long java/lang/reflect/Modifier + (#static isStatic [int] boolean) + (#static isFinal [int] boolean) + (#static isInterface [int] boolean) + (#static isAbstract [int] boolean)) + +(import: #long java/lang/reflect/Field + (getDeclaringClass [] (java/lang/Class java/lang/Object)) + (getModifiers [] int) + (getGenericType [] java/lang/reflect/Type)) + +(import: #long java/lang/reflect/Method + (getName [] java/lang/String) + (getModifiers [] int) + (getDeclaringClass [] (java/lang/Class java/lang/Object)) + (getTypeParameters [] (Array (java/lang/reflect/TypeVariable java/lang/reflect/Method))) + (getGenericParameterTypes [] (Array java/lang/reflect/Type)) + (getGenericReturnType [] java/lang/reflect/Type) + (getGenericExceptionTypes [] (Array java/lang/reflect/Type))) + +(import: #long (java/lang/reflect/Constructor c) + (getModifiers [] int) + (getDeclaringClass [] (java/lang/Class c)) + (getTypeParameters [] (Array (java/lang/reflect/TypeVariable (java/lang/reflect/Constructor c)))) + (getGenericParameterTypes [] (Array java/lang/reflect/Type)) + (getGenericExceptionTypes [] (Array java/lang/reflect/Type))) + +(import: #long (java/lang/Class c) + (#static forName [java/lang/String] #try (java/lang/Class java/lang/Object)) + (getName [] java/lang/String) + (getModifiers [] int) + (isAssignableFrom [(java/lang/Class java/lang/Object)] boolean) + (getTypeParameters [] (Array (java/lang/reflect/TypeVariable (java/lang/Class c)))) + (getGenericInterfaces [] (Array java/lang/reflect/Type)) + (getGenericSuperclass [] #? java/lang/reflect/Type) + (getDeclaredField [java/lang/String] #try java/lang/reflect/Field) + (getConstructors [] (Array (java/lang/reflect/Constructor java/lang/Object))) + (getDeclaredMethods [] (Array java/lang/reflect/Method))) + +(exception: #export (unknown-class {class Text}) + (exception.report + ["Class" (%t class)])) + +(template [] + [(exception: #export ( {jvm-type java/lang/reflect/Type}) + (exception.report + ["Type" (java/lang/reflect/Type::getTypeName jvm-type)]))] + + [not-a-class] + [cannot-convert-to-a-parameter] + [cannot-convert-to-a-lux-type] + ) + +(def: #export (load name) + (-> Text (Error (java/lang/Class java/lang/Object))) + (case (java/lang/Class::forName name) + (#error.Success [class]) + (#error.Success class) + + (#error.Failure error) + (exception.throw ..unknown-class name))) + +(def: #export (sub? super sub) + (-> Text Text (Error Bit)) + (do error.monad + [super (..load super) + sub (..load sub)] + (wrap (java/lang/Class::isAssignableFrom sub super)))) + +(def: #export (generic reflection) + (-> java/lang/reflect/Type (Error /.Generic)) + (<| (case (host.check java/lang/reflect/TypeVariable reflection) + (#.Some reflection) + (#error.Success (#/.Var (java/lang/reflect/TypeVariable::getName reflection))) + _) + (case (host.check java/lang/reflect/WildcardType reflection) + (#.Some reflection) + (case [(array.read 0 (java/lang/reflect/WildcardType::getLowerBounds reflection)) + (array.read 0 (java/lang/reflect/WildcardType::getUpperBounds reflection))] + (^template [ ] + + (do error.monad + [bound (generic bound)] + (wrap (#/.Wildcard (#.Some [ bound]))))) + ([[_ (#.Some bound)] #/.Upper] + [[(#.Some bound) _] #/.Lower]) + + [#.None #.None] + (#error.Success (#/.Wildcard #.None))) + _) + (case (host.check java/lang/Class reflection) + (#.Some class) + (let [class-name (|> class + (:coerce (java/lang/Class java/lang/Object)) + java/lang/Class::getName)] + (case class-name + (^template [] + (^ (static )) + (exception.throw ..not-a-class reflection)) + ([reflection.boolean] [reflection.byte] [reflection.short] [reflection.int] + [reflection.long] [reflection.float] [reflection.double] [reflection.char]) + + _ + (if (text.starts-with? /.array-prefix class-name) + (exception.throw ..not-a-class reflection) + (#error.Success (#/.Class class-name (list)))))) + _) + (case (host.check java/lang/reflect/ParameterizedType reflection) + (#.Some reflection) + (let [raw (java/lang/reflect/ParameterizedType::getRawType reflection)] + (case (host.check java/lang/Class raw) + (#.Some raw) + (do error.monad + [paramsT (|> reflection + java/lang/reflect/ParameterizedType::getActualTypeArguments + array.to-list + (monad.map @ generic))] + (wrap (#/.Class (|> raw + (:coerce (java/lang/Class java/lang/Object)) + java/lang/Class::getName) + paramsT))) + + _ + (exception.throw ..not-a-class raw))) + _) + ## else + (exception.throw ..cannot-convert-to-a-lux-type reflection))) + +(def: #export (type reflection) + (-> java/lang/reflect/Type (Error /.Type)) + (<| (case (host.check java/lang/Class reflection) + (#.Some reflection) + (case (|> reflection + (:coerce (java/lang/Class java/lang/Object)) + java/lang/Class::getName) + (^template [ ] + (^ (static )) + (#error.Success )) + ([reflection.boolean /.boolean] + [reflection.byte /.byte] + [reflection.short /.short] + [reflection.int /.int] + [reflection.long /.long] + [reflection.float /.float] + [reflection.double /.double] + [reflection.char /.char]) + + class-name + (if (text.starts-with? /.array-prefix class-name) + (.run /.parse-signature (/.binary-name class-name)) + (#error.Success (/.class class-name (list))))) + _) + (case (host.check java/lang/reflect/GenericArrayType reflection) + (#.Some reflection) + (|> reflection + java/lang/reflect/GenericArrayType::getGenericComponentType + type + (:: error.monad map (/.array 1))) + _) + ## else + (:: error.monad map (|>> #/.Generic) + (..generic reflection)))) + +(def: #export (return reflection) + (-> java/lang/reflect/Type (Error /.Return)) + (case (host.check java/lang/Class reflection) + (#.Some class) + (case (|> class + (:coerce (java/lang/Class java/lang/Object)) + java/lang/Class::getName) + (^ (static reflection.void)) + (#error.Success #.None) + + _ + (:: error.monad map (|>> #.Some) + (..type reflection))) + + #.None + (:: error.monad map (|>> #.Some) + (..type reflection)))) + +(exception: #export (cannot-correspond {class (java/lang/Class java/lang/Object)} + {type Type}) + (exception.report + ["Class" (java/lang/Object::toString class)] + ["Type" (%type type)])) + +(exception: #export (type-parameter-mismatch {expected Nat} + {actual Nat} + {class (java/lang/Class java/lang/Object)} + {type Type}) + (exception.report + ["Expected" (%n expected)] + ["Actual" (%n actual)] + ["Class" (java/lang/Object::toString class)] + ["Type" (%type type)])) + +(exception: #export (non-jvm-type {type Type}) + (exception.report + ["Type" (%type type)])) + +(def: #export (correspond class type) + (-> (java/lang/Class java/lang/Object) Type (Error Mapping)) + (case type + (#.Primitive name params) + (let [class-name (java/lang/Class::getName class) + class-params (array.to-list (java/lang/Class::getTypeParameters class)) + num-class-params (list.size class-params) + num-type-params (list.size params)] + (if (text@= class-name name) + (if (n/= num-class-params num-type-params) + (|> params + (list.zip2 (list@map (|>> java/lang/reflect/TypeVariable::getName) + class-params)) + (list@fold (function (_ [name paramT] mapping) + (dictionary.put name paramT mapping)) + /lux.fresh) + #error.Success) + (exception.throw ..type-parameter-mismatch [num-class-params num-type-params class type])) + (exception.throw ..cannot-correspond [class type]))) + + (#.Named name anonymousT) + (correspond class anonymousT) + + _ + (exception.throw ..non-jvm-type [type]))) + +(exception: #export (mistaken-field-owner {field java/lang/reflect/Field} + {owner (java/lang/Class java/lang/Object)} + {target (java/lang/Class java/lang/Object)}) + (exception.report + ["Field" (java/lang/Object::toString field)] + ["Owner" (java/lang/Object::toString owner)] + ["Target" (java/lang/Object::toString target)])) + +(template [] + [(exception: #export ( {field Text} + {class (java/lang/Class java/lang/Object)}) + (exception.report + ["Field" (%t field)] + ["Class" (java/lang/Object::toString class)]))] + + [unknown-field] + [not-a-static-field] + [not-a-virtual-field] + ) + +(def: #export (field field target) + (-> Text (java/lang/Class java/lang/Object) (Error java/lang/reflect/Field)) + (case (java/lang/Class::getDeclaredField field target) + (#error.Success field) + (let [owner (java/lang/reflect/Field::getDeclaringClass field)] + (if (is? owner target) + (#error.Success field) + (exception.throw ..mistaken-field-owner [field owner target]))) + + (#error.Failure _) + (exception.throw ..unknown-field [field target]))) + +(template [ ] + [(def: #export ( field class) + (-> Text (java/lang/Class java/lang/Object) (Error [Bit /.Type])) + (do error.monad + [fieldJ (..field field class) + #let [modifiers (java/lang/reflect/Field::getModifiers fieldJ)]] + (case (java/lang/reflect/Modifier::isStatic modifiers) + (|> fieldJ + java/lang/reflect/Field::getGenericType + ..type + (:: @ map (|>> [(java/lang/reflect/Modifier::isFinal modifiers)]))) + (exception.throw [field class]))))] + + [static-field ..not-a-static-field #1 #0] + [virtual-field ..not-a-virtual-field #0 #1] + ) diff --git a/stdlib/source/lux/target/jvm/type/lux.lux b/stdlib/source/lux/target/jvm/type/lux.lux new file mode 100644 index 000000000..92bc05091 --- /dev/null +++ b/stdlib/source/lux/target/jvm/type/lux.lux @@ -0,0 +1,109 @@ +(.module: + [lux (#- type) + [abstract + ["." monad (#+ do)]] + [control + ["." exception (#+ exception:)]] + [data + ["." text + format] + [collection + [array (#+ Array)] + ["." dictionary (#+ Dictionary)]]] + [type + abstract + ["." check (#+ Check) ("#@." monad)]]] + ["." // + ["#." reflection]]) + +(template [] + [(abstract: #export ( class) {} Any)] + + [Lower] [Upper] + ) + +(type: #export Mapping + (Dictionary //.Var Type)) + +(def: #export fresh + Mapping + (dictionary.new text.hash)) + +(exception: #export (unknown-var {var //.Var}) + (exception.report + ["Var" (%t var)])) + +(def: (generic mapping input) + (-> Mapping //.Generic (Check Type)) + (case input + (#//.Var var) + (case (dictionary.get var mapping) + #.None + (check.throw ..unknown-var var) + + (#.Some type) + (check@wrap type)) + + (#//.Wildcard wildcard) + (case wildcard + #.None + (do check.monad + [[id type] check.existential] + (wrap type)) + + (#.Some [bound limit]) + (do check.monad + [limitT (generic mapping limit)] + (case bound + (^template [ ] + + (wrap (.type ( limitT)))) + ([#//.Lower ..Lower] + [#//.Upper ..Upper])))) + + (#//.Class name parameters) + (do check.monad + [parametersT+ (monad.map @ (generic mapping) parameters)] + (wrap (#.Primitive name parametersT+))))) + +(def: #export (class mapping [name parameters]) + (-> Mapping //.Class (Check Type)) + (do check.monad + [parametersT+ (monad.map @ (..generic mapping) parameters)] + (wrap (#.Primitive name parametersT+)))) + +(def: #export (type mapping input) + (-> Mapping //.Type (Check Type)) + (case input + (#//.Primitive primitive) + (check@wrap (case primitive + #//.Boolean (#.Primitive //reflection.boolean #.Nil) + #//.Byte (#.Primitive //reflection.byte #.Nil) + #//.Short (#.Primitive //reflection.short #.Nil) + #//.Int (#.Primitive //reflection.int #.Nil) + #//.Long (#.Primitive //reflection.long #.Nil) + #//.Float (#.Primitive //reflection.float #.Nil) + #//.Double (#.Primitive //reflection.double #.Nil) + #//.Char (#.Primitive //reflection.char #.Nil))) + + (#//.Generic generic) + (..generic mapping generic) + + (#//.Array elementT) + (case elementT + (#//.Primitive primitive) + (check@wrap (#.Primitive (//.descriptor (//.array 1 input)) #.Nil)) + + _ + (do check.monad + [elementT (type mapping input)] + (wrap (.type (Array elementT))))))) + +(def: #export (return mapping input) + (-> Mapping //.Return (Check Type)) + (case input + #.None + (check@wrap Any) + + (#.Some input) + (..type mapping input))) diff --git a/stdlib/source/lux/tool/compiler/phase/extension/analysis/jvm.lux b/stdlib/source/lux/tool/compiler/phase/extension/analysis/jvm.lux index 01265c29a..8679135f1 100644 --- a/stdlib/source/lux/tool/compiler/phase/extension/analysis/jvm.lux +++ b/stdlib/source/lux/tool/compiler/phase/extension/analysis/jvm.lux @@ -11,22 +11,24 @@ ["." exception (#+ exception:)] pipe] [data - ["." error (#+ Error)] + ["." error (#+ Error) ("#@." monad)] ["." maybe] ["." product] ["." text ("#@." equivalence) format] [collection - ["." list ("#@." fold functor monoid)] + ["." list ("#@." fold monad monoid)] ["." array (#+ Array)] ["." dictionary (#+ Dictionary)]]] ["." type ["." check (#+ Check) ("#@." monad)]] [target ["." jvm #_ - ["#" type (#+ Var Bound Primitive Generic Class Type Argument Return Typed) + [".!" reflection] + ["#" type (#+ Var Bound Primitive Generic Class Type Argument Return Method Typed) ["." box] - ["." reflection]]]]] + ["." reflection] + [".T" lux (#+ Mapping)]]]]] ["." // #_ ["#." common] ["/#" // @@ -46,16 +48,6 @@ (#.Primitive ..inheritance-relationship-type-name (list& class super-class super-interfaces))) -(template [