flat assembler
Message board for the users of flat assembler.

Index > OS Construction > Mathis / GUIL

Thread Post new topic Reply to topic

Joined: 22 Mar 2011
Posts: 272
Location: California
I have been adding the pieces to a scripting language (including a GUI) as I've written my driver collection. recently the GUI part hit a critical mass so I have started to use it in my scripting test bed. I call the GUI component Graphically Unified Interface Linguistics.

... Operating System GUI

Visual Aids:

there is a single-pixel thick border around 3 of the sides to show the pixel border.

when the mouse is over one of the 9 edge segments an animated pointer appears which is intended for sizing the window (actual sizing isn't implemented)

a window that was created but has not yet been hovered over by the mouse has a blue banner on the top of the box.

move the mouse over the window and its top bar will become white.

remove the mouse from the window and the window top bar will become either Grey or stay White based on whether the App is at the top of the layer stack.

move the mouse over either of the two "buttons" at the top right of the window and the color of the specific box will change to denote the hovering.

when holding the right mouse down the icon changes to denote dragging the window.


clicking the top right corner (the red box before hover; blue box after hover) of any window will terminate the app.


holding the right mouse button allows the window to be dragged around the screen.

... Graphically Unified Interface Linguistics
;; Document Structure

GUIL implements a document structure very similar to HTML. every object in the document represents a Rectangular layer in the GUI. a GUIL object within a GUIL object is another rectangle with the one caveat: it is contained / clipped by its parent (the layer that it is expressed within). each GUIL object has a list of properties that describe it. some of the properties are defined by the language. one other distinguishing property of GUIL vs HTML is that the Document is entirely designed to hold program state as well as document information. custom state is shown in the example program and described later.

there are 2 nesting forms:

< (NESTING 1 ) > <>


<> (NESTING 2) <>

Nesting 1: this is the property list. it is a set of expressions in the form of L=R. it looks like a programmatic code block but behaves somewhat differently. it will be described later.

Nesting 2: this is where "children" of any GUIL object is stored. unlike HTML any character codes between the end of the parent and the beginning of the child are ignored. this is pseudo-code for one GUIL object within one GUIL object:

<property list1> <property list2><> <>

child layers have the same fundamental structure as their parent. the GUIL-defined properties (which are in the property lists) are described below:

;; GUIL Caustix
;; Properties that define the document:

;; Position / Size Properties

;; x (Position)

the offset from the left of the rectangle within the parent's rectangle.

;; y (Position)

the offset from the top of the rectangle within the parent's rectangle.

;; dx / width (either one will produce the same result)

the size of the rectangle with respect to the horizontal.

;; dy / height (either one will produce the same result)

the size of the rectangle with respect to the vertical.

these 4 fields (x,y,dx,dy) are in units of Millimeters by default. Mathis supports expressions of other units. the code exploits that support to express the sizes in inches.

;; Content Properties

;; txt (Text)

if you want the rectangle to show text this is the field that'll be used. this is shown in the example script. the right box is formed by concatenating other text during events.

;; rgba (Color)

the colors of the rectangle. the low 32bits are the background color which the rectangle is initialized to. the high 32bits is the color of the text controlled by the txt field.

;; idx (index)

This is a generated constant that specifies the numerical position of the child. the only example of it is on line 4 causes the color to alternate between Blue and Green.

;; Event Properties

;; mouse.over, mouse.out (Mouse Over and Mouse Out)
Mouse Over is shown by moving the Mouse over any of the 15 Green / Blue boxes that read "GUIL 1x1 ... GUIL 1x15". the default to an alternating pattern of green and blue. when moving the Mouse Over the box becomes Red. when leaving the box it returns to the original color. this action is described in the script rather.

;; mouse.move (Mouse Move)
This event executes every frame provided there is movement.

;; mouse.down, mouse.up (Mouse Down and Mouse Up)
these two events are executed when any mouse button is pushed down or up (respectively). Up events are exclusive to the layer associated with the Mouse Down event so the Up event on a layer won't fire without the Down event firing first.

;; mouse.click (Mouse Click)
this event is related to the Mouse Down and Mouse Up events. the Click event is used in the example program. Clicking one of the Green/Blue boxes (when they've turned Red) will cause a string hidden in the layer to be concatenated with the text that is in the large box on the right. if you click the top left "delete text" box (it's always Red) then the text will be cleared out of the large box on the right.

;; Mouse Bubbling

the Mouse Events implement bubbling. if the top-most layer does not have an event, but a parent of the target layer does have an event then the layer with the event will execute. if a second parent has an event then only the first (from the top) parent has its event executed. the "target" variable gives the script access to the target that was hit by the mouse. "this" gives access to the layer which the event is within.

;; Exit Event Property

when the program terminates (by clicking on the top right (Red) button) the document structure is enumerated and every exit program is executed. two of them exist in the example program. the only function for the example program simply reports the exit. for sophisticated programs it allows structured termination: store a "Modified" file data structure in the same (or related) document layer and upon exit flush the modified data to disk.

;; Targeting Properties

Mathis supports more general ways of targeting layers than what is described in the Layer Targeting section that follows this one.

;; Name
;; name

this provides a relative target that is related to ID described next. the object-oriented structures (Classes) I intend for GUIL do not currently exist to put this to use in a way that is unique to the ID mechanism. it is employed in line 68 of the example (and does work) but is not used to any other extent.

;; ID
;; id

set id equal to an identifier of your choosing and that identifier may be used to target the current layer in some other layers event handlers. it must be the root of an identifier when used. the Standard targeting methods follow.

;; ---------------------------------------------
;; Layer Targeting
;; ---------------------------------------------

Mathis implements multiple ways of targeting a specific layer. all properties of the layer associated with the executing code can be accessed implicitly. there is, however, an explicit method of targeting the current layer: this.

;; GUIL Root Layer
;; guil

this is a global pointer to the root of the GUIL Tree. due to all of the methods that follow there is rarely a need to access this directly.

;; Current Layer
;; this

the current layer. implicitly used when targeting a property. the simplest example of "this" is to compare the current object with the target object to protect the code from reading a property that doesn't exist (currently this causes the script to crash rather than returning something like null).

;; Parent Layer
;; p

when you want to target the parent of the layer that is currently executing the global variable "p" is available. it's used repeatedly in the document example. if the current object happens to be the GUIL root then the parent will loop back to the current (p = this = guil).

;; Adjacent Layers. (Siblings)
;; next / prev

when you have multiple GUIL objects inside one GUIL object the "next" and "prev" values will give you the next and previous objects unless it is on the boundary. if it's the boundary then it returns the same layer as the current. which one is next/previous is determined by the expression of the document not the geometry properties.

;; Target for Mouse Events
;; t

when the mouse event bubbles up to a parent layer this provides the top most layer under the mouse during the event. if it's the Mouse Up event then it's the same as the target for the Mouse Down event.

to recap: the properties of the object/layer that is shared with the executing code are implicitly available (or explicitly available via 'this' if you prefer). properties within other objects need to be subscripts (or a chain of subscripts) of one of the targeting methods.

;;;;;;;;;;; Custom State

GUIL is designed to be the State Machine for Applications written in the Mathis language. every document layer supports storing custom state. the custom state can be used as you need it and targeted using the Targeting methods described just above.

;;;;;;;;;;; Special GUIL Tokens

? : this is the Imposition character which is prefixed to an L-value within the Document Property Lists. it causes the engine to duplicate the R-value into every child of the object that doesn't have a corresponding property. this is largely a compression tool as it avoids typing out (and generating the corresponding memory) the property in every child of the object.

Mathis Script

the actual scripting language is relatively straight forward for anyone who has written code before.

Data Directives (L = R)

 let VariableName = Expression    

the maximum number of characters in VariableName is 15, it must begin with a letter of either CaSe and may contain numbers but not any special symbols as they are reserved for future use as tokens. Data statements are terminated by a vertical bar (|) however they may also be terminated by a semi-colon. if you use a semi-colon then any text that follows is considered commentary (just as it is in FASM). alternatives to "let" are usable but they have no effect on the behavior:

int variable = expression;
ape variable = expression;
string variable = expression;    

Expression supports expressions of other, previously defined, variables and operators:
Precedence Group 1 (this evaluates last):
@ : String Concatenation (if the object isn't a string then a subjective string is generated that is representative of the value).

Precedence Group 2:
=  : Comparison. produces an integer (0=False,1=True) from the result.
$  : Type Comparison. only looks at the type of the variable. output is an integer just the like the equality operator.
<  : Less than. output is an integer 0,1
>  : Greater than. output is 0,1
<= : Less or equal.
>= : Greater or equal.

Precedence Group 3:
& : Bitfield And.
~ : Bitfield Exclusive OR.

Precedence Group 4:
+ : Addition
- : Subtraction

Precedence Group 5:
*  : Multiplication
/  : Division
<< : Shift left. this is continuous. is basically a multiple of a power of two.
>> : Shift right. this is continuous. same as left shift except represents Division.

Precedence Group 6 (highest Precedence evaluates first):
^ : Power. i.e., 10 ^ 2 = 100.    

Control Directives:

if  expr

if the expr is true then the code executes. expr is in the same format as the R component in the L=R Data Declaration.

if expr
    code 2

this is the same as if except the else case executes when the expr (expression) is false.

dbg (debugging aid):
 dbg "Hello World";
dbg Expression;    

this is a simple tool for painting debugging statements to the window. Expression may be any expression just like the R-value in a Data Declaration.

while expression

a while block executes the code block as long as the expression evaluates to true.

return expression    

this is used for function calls to execute a return to caller. the expression is evaluated then in the context of the function and it's result becomes an R-value in the caller expression.

order: this is currently a simple function definition. like the GUIL document forward referencing is implemented to call these functions. I intend to develop this further so the following is the simplest definition:
order FunctionName(InputParameterList)
    code line 0
    code line 1
    etc ...

the Input parameter list in a coma-delimited list (the comma has the lowest precedence of any binary operator) the number of inputs must match the number of inputs when calling the function:
let FunctionOutput = FunctionName(input)    

functions may be used within expressions in the same way as variable names.

; Attachments:
variables can be more than just scalar values like numbers and strings. they can be Objects and Code variables. these are used via:
 Object: Subscript. place a period after the variable name
Function: Parenthesis. place a pair of parenthesis after the variable name:

Attachments have a higher precedence in decoding the code than any operator (including comma). Arrays were implemented in an earlier version of my code but it was disabled because the appending process was way too hackish to manage in the new code. if you use them don't be surprised if some code works while other doesn't.

; Code Variables:

Mathis supports an inline function definition referred to as a Code Variable. they are related to orders while avoiding the need to pollute the global identifier space for single use functions. the definition is:

let CodeVariable = [parameterList]
    code block;

while these are not intended to be called like a normal function (an order) they can be:
let CodeVariableOutput = CodeVariable(input)    

;; Precision

Mathis implements an extended precision engine. precision goes to nearly 10 000 base-10 digits. each value is internally represented as a sequence of 64bit limbs (base 2^64). the maximum number of limbs that are implemented is 510 during the early processing of constants. at runtime the software has a maximum limb length of 508 due to overhead that is specific to the runtime system. expressions automatically expand to the maximum precision based on the runtime value unless directed otherwise.

;; Script Exemplars (testcode.asm within the root of the Mathis folder)

I've written some orders that perform mathematical functions that you can validate externally (or even internally if you know how inverse functions work):

line 89: log: the Natural Logarithm of the input. this is implemented using the AGM (Arithmetic Geometric Mean). it consumes roughly 150ms to execute 9800 digits of precision.

line 114: exponent: the Natural Exponent of the input (includes a precision modifier). this is the inverse of the log described previously. Mathematically it is usually denoted as "e^x". the algorithm it uses is not as fast as the AGM for the logarithm. it takes approximately 1 second to evaluate the input for almost any input. if you input an integer it'll return a power of a constant of e. this causes the code to execute drastically faster.

line 148: nroot: the nth root of a number. avoid inputs that are of the form (1 + epsilon) * 2^n. it's not resilient for these cases.

line 196: sqrt: the square root of the input. I implemented a square root in the scripting language. simply subscript a number via:

and you'll get the full precision and my algorithm is resilient for novel inputs (including 1+epsilon).

line 286: AGM. this is the general Arithmetic Geometric Mean.

line 308: Pi. this function doesn't have any inputs. it simply returns Pi to the full precision. Gauss–Legendre iterative algorithm

line 340: Pi2. alternative pi calculator. doesn't work faster. Newton-iteration based optimizations in my sqrt code make the higher level code slower.

line 372: another pi calculator. again it's slower than the Gauss-Legendre algorithm.

line 472: ln. another version of the natural logarithm. this one is terribly slow. it's a power series that you either learned in your Calculus course at some point or is related to the one you learned. don't use unless you wanna know why the AGM is better.

line 498: lnWorks.. another logarithm. it's called lnWorks because I was using it to debug the extended precision engine.

line 520: sine. the Trigonometric Sine. Power Series. this is what you learned in your Calculus course. it's slow. it takes atleast a second.

line 545: cosine. Trigonometric Cosine. Power Series. same as since.

line 568: factorial: really old function I wrote for testing the basic parser. not recursive.

;; GUIL Exemplars (testcode.asm within the root of the Mathis folder)

line 2: the root GUIL object is delcared. it is 4 inches tall and 6 inches wide. when exiting it prints "Goodbye from the root"

line 4: this is a container for the Blue/Green column on the left. each box in the column is a separate object. the width of the object 1 inch and the height is the size of the height of the parent: p.dy (which will evaluate to 4 inches).

line 6: this begins the Mouse Click event handler for the Column object. bubbling is used to avoid creating a click handler for every child of this container. line 15 checks whether the target of the mouse click is the same as the container to avoid doing anything when they're the same. the container column is not intended to have behavior on it's own.

line 23: mouse over handler. this records the current RGBA value into custom state (the children can be either blue or green but the container doesn't know so it backs it up). it also writes over the target RGBA field to make it Red.

line 32: mouse out handler. this restores the state of the target after the mouse leaves the object. the alt variable is initialized exclusively by the mouse over code and the mouse out code only executes after mouse over so there is no need to store anything to alt at the end.

line 41: this ends the column container. the text that you see on the same line is essentially cleared making it little more than commentary for the developer to describe was it is. formatting characters, like the visible characters have no effect on the programmatic structure of the document. if you read all of the text there is a set of GUIL objects before the closing character on line 66. these are the guil objects that are visible and manipulable to the user.

line 43: the first child contained by the column object. this one has it's own Click handler that uses the ID target method to write a blank string to its text property (which clears the string)

line 44 through 64: these are each of the remaining children for the column. the txt property says that "GUIL 1x" will be printed followed by the number of the child. the "custom" property is custom state that is readable and writable by the event handlers. when the user clicks on one of the boxes the custom property is concatenated onto the large area by the parent click handler.

line 66: this terminates the Column container.

line 68: this is the large rectangle on the right of the window with the text "default text". it has the same height as the parent. its position is related to the Column: the width of the column plus the position. the width is calculated as the remaining space: the parent width minus the width of the column. an ID is defined for this object that allows any event handler to access it's properties with the identifier "prime". the RGBA field defines the foreground and background colors. this object doesn't have any children but it does have some text which is ignored on the following lines.

line 72: the terminal character for the rectangle that started on line 68.

line 74: the terminal character for the root GUIL object. this ends the GUIL object. the code is now back in procedural space and executable as normal.

line 76, 77, 78: these are testing some extensions of GUIL. they are properly formed GUIL objects but not used. the types are not yet implemented.

line 85, 86, 87: the GUIL tokens are not ASCII codes; they are UTF-8 extended codes (above 127, below 256). I use this to copy and paste objects. using non-ASCII characters helps to avoid a large number of nesting issues that are notoriously well defined (pun intended) among the HTML community.

line 85: this causes the string "runtime started" to be printed telling the user that the script has begun executing. a corresponding dbg statement exists on line 614 that executes when the global script section ends executing.

line 86 ... 613 a collection of orders described earlier.

line 614: the end of runtime dbg statement.

Finishing Notes:

I also have keyboard events defined but my keyboard drivers aren't linked with the GUI system yet.

the zip file included contains the source code and two IMG files. one is intended for vmWare while the other is for VirtualBox. if you test on real hardware it won't matter which one you use. Emulators such as vmWare and VirtualBox don't implement an EDID for the monitor. the EDID is necessary to specify the physical units that GUIL uses. if you run this on real hardware then the EDID will have precedence and ignore the constants supplied. if you're running an enumator the physical units won't be correct.

Notable Limitations:

there is a fairly large limitation in the rendering side. objects need to be fully visible or fully hidden to avoid abhorrent behavior. an object that is partially occluded will paint outside the window. ordering of the layers can obscure this issue.

text painting is not sophisticated: it simply paints each character until it runs out of space then goes to the next line.


Filename: Mathis.zip
Filesize: 1.36 MB
Downloaded: 42 Time(s)

byte me.
Post 17 Dec 2019, 19:02
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum

Copyright © 1999-2020, Tomasz Grysztar.

Powered by rwasa.