7mind / izumi Goto Github PK
View Code? Open in Web Editor NEWProductivity-oriented collection of lightweight fancy stuff for Scala toolchain
Home Page: https://izumi.7mind.io
License: BSD 2-Clause "Simplified" License
Productivity-oriented collection of lightweight fancy stuff for Scala toolchain
Home Page: https://izumi.7mind.io
License: BSD 2-Clause "Simplified" License
scala-asm only, classloaders should be provided by a policy
def hello(thing: String) {
val context = new {
val x = 1
val arg = thing
}
context.debug("Printing...")
}
def hello(thing: String) {
object context {
val x = 1
val arg = thing
}
context.debug("Printing...")
}
def hello(thing: String) {
val context = logger.withContext (
"x" -> 1
, "y" -> thing
)
context.debug("Printing...")
}
At one hand we resolve at with factories, at the other hand it still may be convenient. Some ideas:
@Prototype
annotation at usage pointNote: factories are different. Also I don't have any sane usage scenario for this at the moment, but let's keep it.
How long would it take to instantiate a context with 10K instances?
val inDirectory = In("directory").settings(LibSettings)
We should be able to provide a logback-styled pattern, then iterate over it and append message elements according to placeholders
「If you don't have a test for it – it doesn't exist.」 – much wise philosof
We should be able to accept messages coming from slf4j-enabled libraries
Artifact stub: logstage-adapter-slf4j
The proposal:
fundamentals/izumi-config
or smth like thatlogstage-typesafe-config
and reuse the mapperShould be implemented after #38
Decorator for an arbitrary sink. Should maintain a queue and perform the actual flushing in a separate thread (or a shared Executor)
We need to correctly resolve types referenced from other domains within our scope
Technically, we have enough data for that.
A trait:
// class version 52.0 (52)
// access flags 0x601
public abstract interface org/bitbucket/pshirshov/izumi/distage/Case2$ATrait {
// compiled from: Fixtures.scala
ATTRIBUTE Scala : unknown
ATTRIBUTE ScalaInlineInfo : unknown
// access flags 0x609
public static abstract INNERCLASS org/bitbucket/pshirshov/izumi/distage/Case2$ATrait org/bitbucket/pshirshov/izumi/distage/Case2 ATrait
// access flags 0x401
public abstract org$bitbucket$pshirshov$izumi$distage$Case2$ATrait$_setter_$x_$eq(I)V
// parameter final x$1
// access flags 0x401
public abstract x()I
// access flags 0x9
public static $init$(Lorg/bitbucket/pshirshov/izumi/distage/Case2$ATrait;)V
// parameter final synthetic $this
L0
LINENUMBER 85 L0
ALOAD 0
ICONST_1
INVOKEINTERFACE org/bitbucket/pshirshov/izumi/distage/Case2$ATrait.org$bitbucket$pshirshov$izumi$distage$Case2$ATrait$_setter_$x_$eq (I)V
L1
LINENUMBER 84 L1
RETURN
L2
LOCALVARIABLE $this Lorg/bitbucket/pshirshov/izumi/distage/Case2$ATrait; L0 L2 0
MAXSTACK = 2
MAXLOCALS = 1
}
And corresponding class:
// class version 52.0 (52)
// access flags 0x21
public class org/bitbucket/pshirshov/izumi/distage/Case2$AClass implements org/bitbucket/pshirshov/izumi/distage/Case2$ATrait {
// compiled from: Fixtures.scala
ATTRIBUTE Scala : unknown
ATTRIBUTE ScalaInlineInfo : unknown
// access flags 0x9
public static INNERCLASS org/bitbucket/pshirshov/izumi/distage/Case2$AClass org/bitbucket/pshirshov/izumi/distage/Case2 AClass
// access flags 0x609
public static abstract INNERCLASS org/bitbucket/pshirshov/izumi/distage/Case2$ATrait org/bitbucket/pshirshov/izumi/distage/Case2 ATrait
// access flags 0x12
private final I x
// access flags 0x1
public x()I
L0
LINENUMBER 88 L0
ALOAD 0
GETFIELD org/bitbucket/pshirshov/izumi/distage/Case2$AClass.x : I
IRETURN
L1
LOCALVARIABLE this Lorg/bitbucket/pshirshov/izumi/distage/Case2$AClass; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 0x1
public org$bitbucket$pshirshov$izumi$distage$Case2$ATrait$_setter_$x_$eq(I)V
// parameter final x$1
L0
LINENUMBER 88 L0
ALOAD 0
ILOAD 1
PUTFIELD org/bitbucket/pshirshov/izumi/distage/Case2$AClass.x : I
RETURN
L1
LOCALVARIABLE this Lorg/bitbucket/pshirshov/izumi/distage/Case2$AClass; L0 L1 0
LOCALVARIABLE x$1 I L0 L1 1
MAXSTACK = 2
MAXLOCALS = 2
// access flags 0x1
public <init>()V
L0
LINENUMBER 88 L0
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
ALOAD 0
INVOKESTATIC org/bitbucket/pshirshov/izumi/distage/Case2$ATrait.$init$ (Lorg/bitbucket/pshirshov/izumi/distage/Case2$ATrait;)V
RETURN
L1
LOCALVARIABLE this Lorg/bitbucket/pshirshov/izumi/distage/Case2$AClass; L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
}
So, what we need to do:
vals
. This is the most problematic part, seems like we can't distinguish between method and val
Also see grafter API for inspiration (?)
We wish to be as independent of jvm specifics as possible
scala.js
does not support any runtime scala-reflect
symbols, including TypeTags
, Tree
and Universe
: https://groups.google.com/forum/#!topic/scala-js/xY4Iuq8PVvA
We have runtime instances of TypeTags, Types, Annotations and Universe in distage-core.
Note that we can fully use all of scala-reflect, but only in macros.
We can replace all of these and provide working a impl on scala.js (only distage-static module, but right now it's on par in features and flexibility) by following these steps:
Tag
and TagK
instead of TypeTag
in APIs.SafeType
on scala.js. It may be as simple as a macro that .toStrings a TypeTag.Annotation
on scala.js. That means a wrapper API that doesn't (publicly) expose underlying Tree
on JVM.RuntimeDIUniverse
on scala-js that doesn't reference mirror
and Universe
Alternatively, there's a project underway to get cross-platform scala-reflect
... https://github.com/portable-scala/reflect ; However, it's likely to not get anywhere, so we shouldn't rely on them.
The only meaningful way to check a plan is to just run the planner inside a macro.
That means the check has to be done at top-level, when all modules have been merged into one module. This also means that module merges have to be defined at type level or macro/compiler-plugin level.
What meaningful checks are there?
application-reference.conf
and that there are no redundant keys.Type checking dynamic modules:
Let's say there is a module that we change at runtime, depending on config, that means we have 2 possible static configurations: mod1 ++ mods
and mod2 ++ mods
. If we naively check both configurations, we'd need to run the macro twice. If we add more modules, the number of possible configurations grows exponentially. At 16 dynamic modules, we'd have to run the macro 65536 times, which would definitely slow down our compilation!
We may do it another way though:
define top-level module as a set of Variants of modules (TargetPoints
in old izumitk)
// Modules with `||` have dynamic variants, modules without are fully static
new ProgramDef {
val moduleVariants = Seq(
(customerRepoImpl1 || customerRepoImpl2)
,(userRepoImpl1 || userRepoImpl2)
,(facebookNotifications || twitterNotifications)
, staticModules // no `||` operator here, this part is static and doesn't change
)
}
Now extract the full static part of the program:
// You can also say that we are extracting
interfaces from modules. We can do that too. Instead of calculating the intersection between all variants = just require them to define and inherit an interface and check the interface. We'd have to use explicit interfaces to support plugins
Now check the dynamic part of the program:
That means that instead of running the macro 65536 times, we only need to run it once, and check each variant once.
This typing mechanism is somewhat more restrictive, but it rules out invalid cases such as for example, there are 2 target points: Impl, Logger
and 4 modules DummyLogger, DummyImpl, RealLogger, RealImpl
.
DummyImpl can only work with DummyLogger and RealLogger can only work with RealLogger:
class RealImpl(logger: RealLogger) extends Impl
So there are 2 valid configurations possible:
Logger = DummyLogger
Impl = DummyImpl
and
Logger = RealLogger
Impl = RealImpl
But there are also 2 invalid configurations:
Logger = DummyLogger
Impl = RealImpl
and
Logger = RealLogger
Impl = DummyImpl
In our typing scheme the user will get errors such as:
In variant RealImpl of Impl: RealLogger is not part of static context. Provided dynamically by RealLogger variant of Logger. Logger has variant DummyLogger, that does not proviode RealLogger.
In variant DummyImpl of Impl: DummyLogger is not part of static context. Provided dynamically by DummyLogger of Logger. Logger has variant RealLogger, that does not proviode DummyLogger.
To remove the error, user will have to remove the Logger target point and put the logger inside the *Impl modules:
object RealImpl extends ModuleDef {
make[RealLogger]
make[Impl].from[RealImpl]
}
Now there are only 2 possible configurations, and both are valid:
Impl = RealImpl | DummyImpl
IMHO this is a good thing, even though the user can't split the Logger
inside into its own target point, the split was nonsensical to begin with and only added invalid configurations to the program.
Depends on #102
NB type level impl: HList Cons on single bindings could slow down the compiler a lot. should instead append HLists of HLists
NB performance: Running the planner at every recompile may not be fast at all! the user would have to be provided with performance diagnostics and a way to disable the checks or enable them selectively (i.e. disable for dev, enable in ci)
Just for debug purposes
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.