diff --git a/documentation/Concepts/context.xml b/documentation/Concepts/context.xml index 16a26ec..8d1cd0a 100644 --- a/documentation/Concepts/context.xml +++ b/documentation/Concepts/context.xml @@ -1,304 +1,312 @@ <?xxe-sn 2ahi4rjnvuo 2?>Context Computer program, its internal states and transitions between them can be looked at from two different points of view: control flow and data flow. In order to express and employ control flow related program's properties Xreate supports mechanism called context — ability to assign transcend data to a code blocks in a way that related blocks in the CFG have - related contexts. + related contexts. Code block's context is exhaustingly defined as follows: Block's place within the code in terms of hierarchy of all its respective parents. Historical data determined by previous visited code blocks in terms of "caller-callee" relation graph. Block level annotations are used to define context and reason about it. See syntax.
<?xxe-sn 2ahi4rjnvuo e?>Examples of Context Usage: Suggestions and Requirements //someStringFn = function:: string {...} main = function:: string; entry { context:: env(utf8). someStringFn() } In this example the annotation env(utf8) conveys some information about the block thus distinguishing it from the others, which allows to apply specific compilation rules for this block. Suppose someStringFn has different specializations for different environments. Now it's possible to invoke specialization tailored for UTF8 environment. In this case context can be viewed as a suggestion - to pick up appropriate specialization. + to pick up appropriate specialization. Also there is possibility to define expected context properties: name - "...." guard:: safe { crucialOperation = function:: int {0} } main = function:: int; entry { context:: env(safe). crucialOperation() } Function crucialOperation has only one specialization safe in the example. If the context does not provide required environment env(safe)compiler can't find appropriate specialization and reports compilation error. This is a way for function to express requirements or contract to a context it works within.
<?xxe-sn 2ahi4rjnvuo r?>Context Propagation Context propagation means that contexts of different blocks are connected reflecting control flow. Context of a particular code block is - gathered from following sources: + gathered from following sources: Local context — annotations that are defined within the block Parent context. Block's context inherits context of its parent reflecting block's place within a program. Client context. Blocks context also includes caller's context reflecting control flow. It allows taking into account in which context a given code is used. Example below name = "..." //requires 'safe' context guard:: safe { crucialOperation = function(a:: int, b::int):: int { 0 } } test = function:: int; entry { //blockA context:: env(safe). range = [1..10]:: [int]. loop fold(range->x::int, 0->acc):: int { //blockB crucialOperation(x, acc) // In the nested scope env(safe) context still accessible } } demonstrates context propagation to a nested block which is exhibited by availability of a env(safe) annotation in the context of the nested block blockB despite being defined in the blockA. Another case is propagation from caller to a callee. It means context propagates through "caller/callee" relation — callee inherits caller context. The example below demonstrates this: name = "..." toSI = function(x:: int):: int { 0 } calculate = function(x:: int):: int { y = toSI(x):: int. y } test = function:: int; entry { context:: units(mm). calculate(10) } Suppose calculate()works with values measured in different units. It normalizes each value by invoking toSI() conversion. One approach is to keep unit information for each variable independently. But if we know that entire program or a part of it works only with specific unit we can register it in a context, units(mm)in this example, letting functions calculate() and its callees inherit context allowing compiler to generate code tailored for specific units only.
- <?xxe-sn 2ahi4rjnvuo 1n?>Latex (Late Context) + <?xxe-sn 2ahi4rjnvuo 1n?>Latex (Late + Context) + + + + + This section is still incomplete. It will + be reworked soon. + Static(compile-time) context reasoning is weak since it's able to infer only partial context, consisting of properties that are true for all possible paths leading in a CFG to a given block. Beyond that are entries that depend on exact path in CFG. Such uncertainty is possible to resolve during runtime once it's known which path exactly is chosen. To solve this problem late context is introduced - embedding into compiled code certain instructions to gathered data on relevant occasion at runtime to determine exact or strong, context. Latex approach can be described as follows: Set of all possible context facts for the given block is computed during compile time. Each such fact is - associated with code paths it holds for. + associated with code paths it holds for. During execution the information is gathered which facts are hold depending on actual code path. Information stored in the late parameters. To convey late context data the latex parameter is injected into function signature as hidden parameter. Late parameter is used as guard for late transcend facts context consists of. name = "..." import raw ("core/control-context.lp"). compute = function:: int { 0 } computeFast = function:: int { context:: computation(fast). compute() } computePrecisely = function:: int { context:: computation(precise). compute() } test = function(cmnd:: int):: int; entry { context:: arithmetic(iee754). if (cmnd > 0)::int {computePrecisely()} else {computeFast()} } Static scope name = "..." import raw ("core/control-context.lp") case context:: computation(fast) { compute = function:: num { 0 } } case context:: computation(precise) { compute = function:: num { 0 } } executeComputation= function:: num { compute() } test = function(cmnd:: num):: num; entry { if (cmnd > 0)::num { context:: computation(fast). executeComputation() } else { context:: computation(precise). executeComputation() } } To sum it up, context consists of two complements parts: on the one hand static(early) context, that denotes compile time inference's result and on the other hand, late(dynamic) context denotes annotations decided upon at runtime.
diff --git a/documentation/index.xml b/documentation/index.xml index 5033a93..4f76967 100644 --- a/documentation/index.xml +++ b/documentation/index.xml @@ -1,216 +1,216 @@ <?xxe-sn 2b06cb2u4g0 2?>Xreate Manual Xreate is an open source general purpose high level programming language designed to write efficient and safe computer programs. Here "high level" has very specific meaning, implying an ability to easily write, read, as well as adapt software to a constantly changing environment or business goals. In this respect, any software product can be evaluated on the basis of the three dimensions: efficiency, safety, and adaptability. Unfortunately, those properties are proved to be largely contradictory, for it is manageable to write either efficient (yet unsafe) or safe (yet impractical) code, but not both. Thus, the ultimate goal of the language is to allow developers to produce code that would have all these properties at the same time. Xreate's design principles allow to adopt any programming technique as long as it does not improve one dimension at the expense of another. To achieve the aforementioned design goals, Xreate employs three distinctive layers: Brute. The lowest layer is called Brute — this is code that is intended to be actually compiled. Code on this level implements actual software functionality. It resembles the usual imperative languages' apparatus and consists of executable instructions such as arithmetic, branching, input/output, etc. Transcend. Brute level alone is not enough to constitute a full-fledged language since code requires various non-executable metadata to express developer's intents, check correctness, validity and perform other types of analyses. In Xreate everything of this sort belongs to a layer called Transcend. Transcend due to its declarative nature is appropriate to do management-type work — it analyzes, oversees and controls brute by guiding compilation process. Everything on this level — logic or transcend facts and rules — is gathered and sent to an external logic solver to make solutions that are brought back in order to guide compilation. Interpretation. There is also Interpretation — the intermediate level resembling dynamically typed languages that is used as a contact point and interpreter between brute and transcend and their respective low level and high level constructs and structures. On a syntactic level, Xreate is a procedural language with extensive use of annotations — arbitrary unconstrained metadata that software developer can attach to different language constructs, variables and code blocks. Annotations are completely invisible for the compiler proper and used by transcend more as a suggestion conveying additional information. "a different language constructs": если подразумевается "конструкции разных языков", тогда лучше "different languages' constructs". Если конструкции языка, в целом, то тогда артикль a не нужен Most severe and hard to resolve problems in software development stem from interaction of different components on different levels. Each individual component often is thoroughly tested and works reliably. But combining them when building end-user software for which purpose complex interaction and extensive IO is enabled usually leads to a range of runtime errors, security vulnerabilities and performance degradation. Thus Xreate places key emphasis on domain-specific component level improvements and joint use of external resources. This aspect is covered in exploitation and containers chapters. Unlike academic languages, Xreate targets safe and reliable usage of effectful computations such as IO covered in virtualization and exploitation chapters, and mutable structures covered in communication.
<?xxe-sn 2b06cb2u4g0 4?>Basic Example To demonstrate what Xreate is all about, basic example is given below: name="tests/introduction.cpp: Introduction.Doc_Example_1", lines=15 guard:: iAmVeryFast { div = function(a:: float, b:: float):: float { a / b } } guard:: iAmVerySafe { div = function(a:: float, b:: float):: float { if ( b == (0::float)):: float {0::float} else {a / b} } } test = function:: float; entry; iAmVerySecure { div(10, 5) } Here entry point of the program is a function test recognized so by compiler because of annotation entry in its signature. There are also two functions div called specializations. Each specialization has a guard that defines a condition that has to be met in order to invoke this particular specialization. In the example, specializations of div have iAmVeryFast and iAmVerySafe guards, respectively. Let's say that developer specifies two specializations where the first one is a very fast division implementation, while the second one is a very safe division implementation since it checks division by zero, although it is - unacceptably slow due to an extra check instruction. This is a basis of + "unacceptably slow" due to an extra check instruction. This is a basis of polymorphism — client's code test is able to work with any specialization, and compiler must decide which one to invoke with the only hint it has — annotation iAmVerySecure in the function test's signature. "provides two specializations" - возможно, лучший вариант "designates/assigns/allocates two specializations". Или даже просто specifies/indicates. (PS заменил на specifies) "unbearably slow" - я бы заменил на более нейтральное "too slow". Unbearable - это скорее об ощущениях человека. Или, если под "unbearably" имеется в виду "недопустимо медленный", тогда - unacceptably slow. All annotations (except entry) are custom defined by developer itself. This is when transcend comes into play. By adding a transcend rule as shown below it is possible to associate annotation iAmVerySecure with invocation of specialization guarded by iAmVerySafe: name="tests/introduction.cpp: Introduction.Doc_Example_1", lines=15 dfa_callguard(SiteInv, iAmVerySafe):- dfa_callfn(SiteInv, div); SiteInv = s(_, _, ScopeInv); cfa_parent(ScopeInv, function(FnInv)); bind_func(FnInv, iAmVerySecure). Transcend rules are written in ASP syntax — common syntax to write logic programs. This particular rule reads that for any function annotated with iAmVerySecure, certain specialization iAmVerySafe is chosen for div invocation. In this example an appropriate specialization is statically resolved, so the other specialization isn't even compiled. the, потому что их всего две. By providing custom rules it is possible to implement any polymorphism strategy, be it performed statically or dynamically. The example demonstrates basic workflow: transcend gathers available information about a program such as annotations and using custom rules makes a decision to guide compilation process, particularly by selecting appropriate specializations as in the above example.