It started as an innocuous attempt to dry up some controller code.
1 2 3 4 5 6 |
|
I noticed that the same if
statement was used in our config/application.rb to setup the correct logging when Torquebox is running. After searching the rest of the code and seeing the same logic was present in config/environments/development.rb I mistakenly thought, “It can’t be too hard to figure out how to have a method accessible from anywhere in a Rails app.”
How wrong I was!
That said, I came up with two possible solutions. The first was to create a proc, stuff it in a global variable, and then access that from each of the places I needed (the config files and the controller).
1
|
|
While the proc worked, I didn’t think it was the best solution for two structural reasons.
It would have to be defined in application.rb in order to be used in the start up process, but being defined in that file outside of the Application class (so that it could be accessed elsewhere in the app) would be a tad strange.
Usage wise, the syntax of $torquebox_running.call seemed a bit strained to me.
My gut told me that I might be breaking every law in the book by declaring a global proc during the boot-up process of a Rails app. So I decided on a more compartmentalized (though still perhaps not object-oriented) approach to solving the problem.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
1 2 |
|
By wrapping these environment checking methods inside a module and using the handy extend self
, the logic was kept isolated and no awful globals created in the process.
I then required the module in the application.rb above all other requirements and the Application class in order that it would be available in every part of the app (config files, models, controllers, the whole gaggle of them!). So far, this approach is working and allows the logic for checking if Torquebox is running to be stored in a single place.
I still feel like this could be improved, though. Maybe by not using extend self
and instead including the module on any of the classes that need access to these methods it would better keep these Torquebox logic confined to only the places in the app that need access?


Working with probe actions in LTL formulas can sometimes be difficult, as we have manually ``remember'' the occurrence of important actions in the formula. In formulas (1) and (2) above, this was accomplished using the until formula.
Instead of using probe actions we can use so called ``probe states''. In contrast to probe actions, which are enabled in a single transition step only, such probes are persistent from the point in the execution of the program when they are enabled, until they are explicitly deleted.
As an example we instrument the login code of the server in
messenger.erl to record, using the function
mce_erl:probe_state, the fact that a user has logged in:
Similarly we delete the probe state using the function
mce_erl:del_probe_state when a user logs out:
We can test for the existence of a probe state using the function
@mce_erl:has_probe_state@ as exemplified in the function
@logged_on@ in the basicPredicates.erl file which checks if
a user is logged on:
This predicate will be abbreviated as ``t'' below.
We can now reformulate the second property above, removing the until operator and one eventually operator with the operator, which holds if its argument holds over the whole execution trace:
"always ((P and T) => eventually (R or not T))"
Note that since is a state predicate we can safely negate it to compute its logical negation (``the user is not logged on'') whereas the negation of the action predicate in properties (1) and (2) only expresses that the ``logon action is not present in the current transition'' (but it may have occurred earlier in the execution of the program).
Orosz György 2010-06-02


Live coverage: Buffalo Sabres at Tampa Bay Lightning
The Buffalo Sabres play the Tampa Bay Lightning at 7 p.m. in Amalie Arena in Tampa, Fla. Here's what you need to know before the game.
Follow along with the action on the ice through reports from our team and select media accounts:


After a user runs terminal, he creates new file and displays content of working directory to see a new file. Then he copies it into backup file and again checks if current directory contains both files. Now, user moves backup file to the same directory but with different name. Finally he removes both files and he lists content to see if they were removed.
After a user runs terminal, he creates new file using touch file_name command and then he runs ls to list content of working directory to see if it contains file_name file.
Then he copies it into backup file running cp file_name file_name.bkp and again he runs ls to see if current directory contains file_name and file_name.bkp files.
Now, user moves backup file by running command mv file_name.bkp file_name2 and again runs ls to see if current directory contains file_name and file_name2 files.
Finally he removes both files with command rm file_name file_name2 and he runs ls to lists content to check if both files were removed.


About this Application
This Inverted Index allows you to perform quick searches for a number of words. An inverted index consists of a list of all the unique words that appear in any document, and for each word, a list of the documents in which it appears.
How to use the application
1. Upload a valid JSON file
2. Select file to index and use the create index button to generate the index
3. Enter word(s) to search. Then click on all or any of the file you want to search from and use the search icon to search
Upload file
Choose a file to index:
Key:
: Present in entry
: Absent
from entry
Index created for {{ file.name }}
| Word | Document_{{$index + 1}} |
|---|---|
| {{ key }} |
Search
Choose a file to search:
Key:
: Present in entry
: Absent
from entry
Showing search results for {{searchWord}} in {{file.name}}
| Word | Document_{{$index + 1}} |
|---|---|
| {{key}} |


Mantle and Inner Core Namelists¶
Mantle Namelist¶
This namelist defines mantle properties
conductance_ma (default
conductance_ma=0.0
) is a real that defines the conductance (dimensionless) of the mantle.
nRotMa (default
nRotMa=0
) is an integer that defines the rotation of the mantle:
nRotMa=-1
Mantle rotates with prescribed rate (see
omega_ma1
andomega_ma2
below)nRotMa=0
Fixed, non-rotating mantle
nRotMa=1
Mantle rotates according to torques
rho_ratio_ma (default
rho_ratio_ma=1
) is a real which gives the density of the mantle in terms of that of the outer core.omega_ma1 (default
omega_ma1=0.0
) is a real which defines a mantle rotation rate (used whennRotMa=-1
).omegaOsz_ma1 (default
omegaOsz_ma1=0.0
) is a real which prescribes the oscillation frequency of the mantle rotation rate. In this case,omega_ma1
is the amplitude of the oscillation.tShift_ma1 (default
tShift_ma1=0.0
) is a real which defines the time shift of the mantle rotation rateomega_ma1
.omega_ma2 (default
omega_ma2=0.0
) is a real which defines a second mantle rotation rate.omegaOsz_ma2 (default
omegaOsz_ma2=0.0
) is a real which defines the oscillation frequency of the second mantle rotation rateomega_ma2
.tShift_ma2 (default
tShift_ma2=0.0
) is a real which defines the time shift foromega_ma2
.
The resultant prescribed mantle rotation rate is computed as:
omega_ma = omega_ma1*cos(omegaOsz_ma1*(time+tShift_ma1)) + &
omega_ma2*cos(omegaOsz_ma2*(time+tShift_ma2))
ellipticity_cmb (default
ellipticity_cmb=0.0
) is a real which defines the ellipticity of the outer boundary. This is used together withomega_ma1
andomegaOsz_ma1
to represent the effect of a librating ellipsoidal boundary using a radial flow boundary condition.
The following defines the parameters when one wants to excite inertial modes in the system artificially using a method similar to Rieutord et. al 2012 .
amp_mode_ma (default
amp_mode_ma=0.0
) is a real which defines the amplitude of forcing on the outer boundary.omega_mode_ma (default
omega_mode_ma=0.0
) is a real which defines the frequency of forcing on the outer boundary.m_mode_ma (default
m_mode_ma=0
) is an integer which defines the wavenumber of the forced mode.mode_symm_ma (default
mode_symm_ma=0
) is an integer which defines the symmetry of the forced mode.0
is for an equatorially anti-symmetric mode while1
is for an equatorially symmetric mode.
Inner Core Namelist¶
This namelist defines properties of the inner core
sigma_ratio (default
sigma_ratio=0.0
) is a real that defines the conductivity of the inner core with respect to the value of the outer core.sigma_ratio=0
thus corresponds to a non-conducting inner core.
nRotIc (default
nRotIc=0
) is an integer that defines the rotation of the inner core. Behaves the same way asnRotMa
(above).rho_ratio_ic (default
rho_ratio_ic=1.0
) is a real which defines the density of the inner core in terms of that of the outer core.BIC (default
BIC=0.0
) is a real which gives the imposed dipole field strength at the Inner Core Boundary. HavingBIC > 0
implies that the inner core acts as a dipole magnet - as implemented in the DTS experiment at Grenoble, France.Variables prescribing rotation rate of inner core The following variables are used to prescribe rotation rate of the inner core. They behave in the same way as the corresponding variables for the mantle. They are usd only when
nRotIC=0
.omega_ic1 (default
omega_ic1=0.0
)omegaOsz_ic1 (default
omegaOsz_ic1=0.0
)tShift_ic1 (default
tShift_ic1=0.0
)omega_ic2 (default
omega_ic2=0.0
)omegaOsz_ic2 (default
omegaOsz_ic2=0.0
)tShift_ic2 (default
tShift_ic2=0.0
)
As with the mantle, the resultant prescribed rotation rate for the inner core is computed as:
omega_ic = omega_ic1*cos(omegaOsz_ic1*(time+tShift_ic1)) + &
omega_ic2*cos(omegaOsz_ic2*(time+tShift_ic2))
ellipticity_icb (default
ellipticity_cmb=0.0
) is a real which defines the ellipticity of the inner boundary. This is used together withomega_ic1
andomegaOsz_ic1
to represent the effect of a librating ellipsoidal boundary using a radial flow boundary condition.
The following, as for the mantle namelist, is for artificially exciting inertial modes in the spherical shell, but for the inner boundary.
amp_mode_ic (default
amp_mode_ic=0.0
) is a real which defines the amplitude of forcing on the inner boundary.omega_mode_ic (default
omega_mode_ic=0.0
) is a real which defines the frequency of forcing.m_mode_ic (default
m_mode_ic=0
) is an integer which defines the wavenumber of the forced mode.mode_symm_ic (default
mode_symm_ic=0
) is an integer which defines the symmetry of the forced mode.0
is for an equatorially anti-symmetric mode while1
is for an equatorially symmetric mode.


This web application takes the results from VarSim SAMcompare and displays them in an interactive plot. For instructions on how to run SAMcompare, please see [link].
Steps for basic usage:
VarSim provides an easy and flexible way to compare secondary analysis workflows. Alignment Compare is for displaying the accuracy results for alignment tools based on the truth set generated by VarSim. It is able to break down the comparison into different regions of the genome based on the type of variant each read overlaps. The curves are generated by varying the MAPQ cut-off.
The plots are generated by varying the MAPQ cut-off. That is for each point alignments are filtered as greater or equal to the MAPQ value.
VarSim plots Sensitivity (TPR) versus FDR. TPR is defined as TP/(TP+FN) and FDR is defined as FP/(FP+TP).
Points with less than 30% of the reads aligned are not plotted since those are potentially noisy and not so useful.
Display detailed results for alignment comparison.
Please read the help before use.
Contact us at bina.rd@roche.com


Route view player
min lat:
max lat:
min lon:
max lon:
+Start
+Goal
+via
Find route
Transport:
Car
Foot
Make permalink
◀
⬅
⏸
➡
▶
Filter your view
User:
Date: From
, To
360 panoramas
Prefer
Only
No
Note: Max 1000m to play
Routing is powered by
GraphHopper API
Images from
Mapillary
Map:
(C)OpenStreetMap contributors
Display map:
Leaflet
Bug report at
Github


Police searching for missing Florida mother, infant daughter
by Johari CantyWINTER HAVEN, Fla. (WSVN) — Police are searching for a missing Florida woman and her baby daughter.
Investigators said 32-year-old Heather Cunniff and her infant daughter, 3-month-old Destiny, were last seen in Winter Haven on Nov. 6.
“Although we do not suspect foul play, we want to make sure they are both safe since they have not been seen,” Winter Haven Police Chief Charlie Bird told Fox 13.
If you have any information on their whereabouts, call<PHONE_NUMBER>.


Bards gives you access too tons of usefull skills such as tumble, spellcraft, etc; Rdd boosts your str, cons, chras, and gives u immunity to fire and paralysis; and I learned that u can take epic dodge at level 10 on sd. So what I was wondering was how would I use these three classes to build a tank that could deal out dmg, while being able to take hits, and dodge them at the same time?
Any help with this build would be appreciated
Do a searchin the build page for the dazzling dervish (iirc).
That may give you an idea.
Syrath _________________ It's SHADOWDANCER, dammit, shadowdancer!!!
Thanks, I made it and it is a fairly decent build. It has good dodging capability, but I can rarely hit people.
Quote: Posted 11/01/05 21:34:03 (GMT) -- Rileigh
Thanks, I made it and it is a fairly decent build. It has good dodging capability, but I can rarely hit people.
here, use this link to search for your builds easier. and put it in your favorites.


Royal Enfield Himalayan Custom Flat Tracker Showcased At Rider Mania – Details
by Surendhar MRoyal Enfield Himalayan flat tracker will be used for Royal Enfield Slide School which is being inaugurated in collaboration with Big Rock MotoPark
At the opening day of the 2019 Rider Mania, where the RE enthusiasts across the country get together for a blast celebrating motorcycling culture, the leading mid-size capacity two-wheeler maker has announced the debut of its Slide School.
It is nothing but a flat-track training academy as novice and expert riders can come together and learn the art of going sideways. Flat tracking is such an established form of motorsport in the United States and Europe and we are glad that a mainstream brand is finally doing something about it in our country.
The Chennai-based brand will be using the customised Himalayan that has been turned into flat trackers “from the ground for some fun”. The inaugural Royal Enfield Slide School will be hosted at Bengaluru in association with Big Rock MotoPark.
Though the dates and venues are yet to be announced, the maiden round will be held in Bengaluru, in collaboration with Big Rock MotoPark – the professional off-road training facility founded and run by one of India’s top pro bikers, CS Santhosh.
Flat tracking beckons stamina and endurance from the rider as you would have to push the bike on a muddy surface around an oval track in anti-clockwise direction. The lack of front brake will make the flat tracking unique compared to other dirt racing categories.
The Royal Enfield Himalayan flat tracker has been built by America-based S&S Cycles that also produces performance parts for the highly popular Interceptor 650 and Continental GT 650. It is essentially a stripped-down version of the stock dual-purpose adventure tourer as it tips the weighing scale at just 164 kilograms.
Some of the highlighting changes include a high mounted exhaust system, a new sprocket system pertaining to flat tracking, lightweight carbon fibre seat and 18-inch spoked rims up front and rear. Apart from being 30 kilograms lighter than the regular Himalayan, there are no mechanical changes made as the suspension and frame remain stock.


Hi people!
So we have started grasping dsa concepts and solving problems from 12 July.
And we shall continue till September 10
Starting from Algorithms to dynamic programming
-> Each day 5 problems
-> July 12 - September 10
-> For beginners and intermediates
For those who joined today:-
With GitHub , I'll post all information on twitter too.
twitter feed
GitHub link:-
GitHub repo
Star the repo or fork it.
We shall start dsa from today.
For complete cpp fundamentals theory visit :-
CPP Theory
GFG learn C++
DSA ALL TOPICS LINK NEW
Use this course to revise your cpp fundamentals
And if anyone is using any other languages rather than c++ then don't worry.
Syntax may be different but concepts would remain the same!
Try finishing all topics of day 1 by Evening, then we shall solve 1-2 basic cpp questions.
Use the wapp group to discuss among yourselves
If you have any doubts or get stuck somewhere you can discuss here and also ask us for help.
To be more clear
Each day we have 2 tasks to complete.
1. Learn the day's target chapters.
2. Solve questions out of daily given 5 questions.


In this console you will get information, that you need.
Next Car
Previous Car
Delete car
Show cars
Add Car
Vehicle Type
Brand
Model
Construction Year
Fuel Type
Number of seats
Price per day
Count
Picture Link
Edit
Create Customer
Choose Customer
Email
Telephone
Full Name
Edit Customer
Delete Customer
Create rent


Test Your Knowledge
Click start to begin your quiz!
Start
High Score
Question Number Goes Here
Questions Go Here
Answer 1
Answer 2
Answer 3
Answer 4
Submit
High-Score Page
Enter Your Initials to save your score!
Submit
Your Score!
Play Again
Clear Scores


Log onto the VOCP System VOCPweb answering machine interface. You will need to have Javascript enabled and to accept cookies.
VOCP and the VOCPweb interface,(C) 2000-2003 Patrick Deegan, distributed according to the terms and conditions of the GNU GPL. Enjoy!


|
orx
1.x dev
Portable Game Engine
|
Data Structures | |
| struct | orxFILE_INFO |
Macros | |
| #define | orxFILE_KU32_FLAG_INFO_DIRECTORY 0x00000008 |
| #define | orxFILE_KU32_FLAG_INFO_HIDDEN 0x00000004 |
| #define | orxFILE_KU32_FLAG_INFO_NORMAL 0x00000001 |
| #define | orxFILE_KU32_FLAG_INFO_READONLY 0x00000002 |
| #define | orxFILE_KU32_FLAG_OPEN_APPEND 0x40000000 |
| #define | orxFILE_KU32_FLAG_OPEN_BINARY 0x80000000 |
| #define | orxFILE_KU32_FLAG_OPEN_READ 0x10000000 |
| #define | orxFILE_KU32_FLAG_OPEN_WRITE 0x20000000 |
Typedefs | |
| typedef struct __orxFILE_t | orxFILE |
Functions | |
| orxDLLAPI orxSTATUS orxFASTCALL | orxFile_Close (orxFILE *_pstFile) |
| orxDLLAPI orxSTATUS orxFASTCALL | orxFile_Delete (const orxSTRING _zFileName) |
| orxDLLAPI orxBOOL orxFASTCALL | orxFile_Exists (const orxSTRING _zFileName) |
| orxDLLAPI void orxFASTCALL | orxFile_Exit () |
| orxDLLAPI void orxFASTCALL | orxFile_FindClose (orxFILE_INFO *_pstFileInfo) |
| orxDLLAPI orxSTATUS orxFASTCALL | orxFile_FindFirst (const orxSTRING _zSearchPattern, orxFILE_INFO *_pstFileInfo) |
| orxDLLAPI orxSTATUS orxFASTCALL | orxFile_FindNext (orxFILE_INFO *_pstFileInfo) |
| orxDLLAPI const orxSTRING orxFASTCALL | orxFile_GetApplicationSaveDirectory (const orxSTRING _zSubPath) |
| orxDLLAPI const orxSTRING orxFASTCALL | orxFile_GetHomeDirectory (const orxSTRING _zSubPath) |
| orxDLLAPI orxSTATUS orxFASTCALL | orxFile_GetInfo (const orxSTRING _zFileName, orxFILE_INFO *_pstFileInfo) |
| orxDLLAPI orxS64 orxFASTCALL | orxFile_GetSize (const orxFILE *_pstFile) |
| orxDLLAPI orxS64 orxFASTCALL | orxFile_GetTime (const orxFILE *_pstFile) |
| orxDLLAPI orxSTATUS orxFASTCALL | orxFile_Init () |
| orxDLLAPI orxSTATUS orxFASTCALL | orxFile_MakeDirectory (const orxSTRING _zName) |
| orxDLLAPI orxFILE *orxFASTCALL | orxFile_Open (const orxSTRING _zFileName, orxU32 _u32OpenFlags) |
| orxDLLAPI orxS32 orxCDECL | orxFile_Print (orxFILE *_pstFile, const orxSTRING _zString,...) |
| orxDLLAPI orxS64 orxFASTCALL | orxFile_Read (void *_pReadData, orxS64 _s64ElemSize, orxS64 _s64NbElem, orxFILE *_pstFile) |
| orxDLLAPI orxSTATUS orxFASTCALL | orxFile_Remove (const orxSTRING _zFileName) |
| orxDLLAPI orxS64 orxFASTCALL | orxFile_Seek (orxFILE *_pstFile, orxS64 _s64Position, orxSEEK_OFFSET_WHENCE _eWhence) |
| orxDLLAPI void orxFASTCALL | orxFile_Setup () |
| orxDLLAPI orxS64 orxFASTCALL | orxFile_Tell (const orxFILE *_pstFile) |
| orxDLLAPI orxS64 orxFASTCALL | orxFile_Write (const void *_pDataToWrite, orxS64 _s64ElemSize, orxS64 _s64NbElem, orxFILE *_pstFile) |
File / file system module Module that handles file / file system access
| #define orxFILE_KU32_FLAG_INFO_DIRECTORY 0x00000008 |
| #define orxFILE_KU32_FLAG_INFO_HIDDEN 0x00000004 |
| #define orxFILE_KU32_FLAG_INFO_NORMAL 0x00000001 |
| #define orxFILE_KU32_FLAG_INFO_READONLY 0x00000002 |
| #define orxFILE_KU32_FLAG_OPEN_APPEND 0x40000000 |
| #define orxFILE_KU32_FLAG_OPEN_BINARY 0x80000000 |
| #define orxFILE_KU32_FLAG_OPEN_READ 0x10000000 |
| #define orxFILE_KU32_FLAG_OPEN_WRITE 0x20000000 |
Closes an oppened file
| [in] | _pstFile | File's pointer to close |
Deletes a file
| [in] | _zFileName | Full file's path to delete |
| orxDLLAPI orxBOOL orxFASTCALL orxFile_Exists | ( | const orxSTRING | _zFileName | ) |
Checks if a file/directory exists
| [in] | _zFileName | Concerned file/directory |
| orxDLLAPI void orxFASTCALL orxFile_FindClose | ( | orxFILE_INFO * | _pstFileInfo | ) |
Closes a search (frees the memory allocated for this search)
| [in] | _pstFileInfo | Information returned during search |
| orxDLLAPI orxSTATUS orxFASTCALL orxFile_FindFirst | ( | const orxSTRING | _zSearchPattern, |
| orxFILE_INFO * | _pstFileInfo | ||
| ) |
Starts a new file search: finds the first file/directory that will match to the given pattern (ex: /bin/foo*)
| [in] | _zSearchPattern | Pattern used for file/directory search |
| [out] | _pstFileInfo | Information about the first file found |
| orxDLLAPI orxSTATUS orxFASTCALL orxFile_FindNext | ( | orxFILE_INFO * | _pstFileInfo | ) |
Continues a file search: finds the next occurrence of a pattern, the search has to be started with orxFile_FindFirst
| [in,out] | _pstFileInfo | Information about the last found file/directory |
| orxDLLAPI const orxSTRING orxFASTCALL orxFile_GetApplicationSaveDirectory | ( | const orxSTRING | _zSubPath | ) |
Gets current user's application save directory using linux separators (without trailing separator)
| [in] | _zSubPath | Sub-path to append to the application save directory, orxNULL for none |
| orxDLLAPI const orxSTRING orxFASTCALL orxFile_GetHomeDirectory | ( | const orxSTRING | _zSubPath | ) |
Gets current user's home directory using linux separators (without trailing separator)
| [in] | _zSubPath | Sub-path to append to the home directory, orxNULL for none |
| orxDLLAPI orxSTATUS orxFASTCALL orxFile_GetInfo | ( | const orxSTRING | _zFileName, |
| orxFILE_INFO * | _pstFileInfo | ||
| ) |
Retrieves a file/directory information
| [in] | _zFileName | Concerned file/directory name |
| [out] | _pstFileInfo | Information of the file/directory |
Retrieves a file's size
| [in] | _pstFile | Concerned file |
Retrieves a file's time of last modification
| [in] | _pstFile | Concerned file |
Makes a directory, works recursively if needed
| [in] | _zName | Name of the directory to make |
Opens a file for later read or write operation
| [in] | _zFileName | Full file's path to open |
| [in] | _u32OpenFlags | List of used flags when opened |
Prints a formatted string to a file
| [in] | _pstFile | Pointer to the file descriptor |
| [in] | _zString | Formatted string |
| orxDLLAPI orxS64 orxFASTCALL orxFile_Read | ( | void * | _pReadData, |
| orxS64 | _s64ElemSize, | ||
| orxS64 | _s64NbElem, | ||
| orxFILE * | _pstFile | ||
| ) |
Reads data from a file
| [out] | _pReadData | Buffer that will contain read data |
| [in] | _s64ElemSize | Size of 1 element |
| [in] | _s64NbElem | Number of elements |
| [in] | _pstFile | Pointer to the file descriptor |
Removes a file or an empty directory
| [in] | _zFileName | Concerned file / directory |
| orxDLLAPI orxS64 orxFASTCALL orxFile_Seek | ( | orxFILE * | _pstFile, |
| orxS64 | _s64Position, | ||
| orxSEEK_OFFSET_WHENCE | _eWhence | ||
| ) |
Seeks to a position in the given file
| [in] | _pstFile | Concerned file |
| [in] | _s64Position | Position (from start) where to set the indicator |
| [in] | _eWhence | Starting point for the offset computation (start, current position or end) |
Tells the current position of the indicator in a file
| [in] | _pstFile | Concerned file |
| orxDLLAPI orxS64 orxFASTCALL orxFile_Write | ( | const void * | _pDataToWrite, |
| orxS64 | _s64ElemSize, | ||
| orxS64 | _s64NbElem, | ||
| orxFILE * | _pstFile | ||
| ) |
Writes data to a file
| [in] | _pDataToWrite | Buffer that contains the data to write |
| [in] | _s64ElemSize | Size of 1 element |
| [in] | _s64NbElem | Number of elements |
| [in] | _pstFile | Pointer to the file descriptor |


FOCUS
Reviewed by Harvey Karten Paramount Classics Director: Neal Slavin Writer: Kendrew Lascelles, Arthur Miller (novel) Cast: William H. Macy, Laura Dern, David Paymer, Meat Loaf Aday
Former Cambodian leader and all-around nut-case Pol Pot-- responsible for killing perhaps one-fourth of his own people during his administration--issued an order to murder everyone in his country who wore glasses. He was not a lobbyist for the new Lasik laser treatment that allows you to "throw your glasses away." Though Pol Pot was one of the most myopic rulers of the 20th Century, he simply believed that people with weak eyes could pick rice, no problem, but that those who took the trouble to correct their vision must be readers. If they're readers, then they're intellectuals and if they're intellectuals, they're a danger to his style of government. QED. Wearing glasses could get people in trouble even if they live far from Phnom Penh. There are still some anti-Semites in the U.S. who believe that what you wear on your nose has something to do with your religious preferences: specifically that you're likely to be Jewish. Sounds strange, but then, anti-Semites are mighty strange people.
Arthur Miller, known as arguably America's greatest 20th Century playwright, belted out a novel in 1945 about how one guy in Brooklyn is targeted as a Jew from the time he popped on his first pair of glasses. Winningly adapted from The Great Writer's novel, Neal Slavin's "Focus" gets its heft largely from the casting of David Mamet's favorite actor, William H. Macy, in the role of a quiet, unmarried Christian living in a nondescript Brooklyn neighborhood during the height of World War II. "Focus" looks for the most part like a work that would be dynamite on the off-Broadway stage or on a 36-inch TV rather than the big screen, and the script by Kendrew Lascelles lacks wit-- but then again Arthur Miller has frequently been criticized for a certain clunkiness in his prose and a suffocating case of self- righteousness. Nonetheless, the film works on two levels: on a didactic one to enlighten people about the presence and dangers of hatred; on an entertainment level given the frequent injections of humor supplied by Laura Dern in the role of a seductively- dressed woman and Macy himself as a Woody-Allen style wimp who when confronted by an extremist for his lack of enthusiasm for the cause excuses himself by saying simply "I never applaud."
At a time that hate groups in the U.S. have already carried atrocities such as the infamous Oklahoma City bombing of a federal building and alleged overreactions have been taken by the U.S. government such as that pursued against a cult in Waco, Texas, we are not surprised to discover that our country has a history of zealotry against people who are "different" dating back to the Salem Witch trials, running through the campaigns of the Know Nothing party against immigration, right up to the present existence of skinheads types hiding out in the woods from New Jersey to Oregon. But you may not have known (I didn't at any rate) that a virulent anti-Semitic group carried out activities in my own home town, Brooklyn, New York, during the height of World War II when our country was presumably fighting against the archcriminal of religious hatred in Europe. "Focus" shows us a remarkable transformation of thought by Newman (William H. Macy), a personnel manager overseeing an office of women at typewriters, who is under orders to hire only Christians. (In one scene, the camera hones in on a newspaper's help wanted ad with the caveat "Christians only"--an advisory that I can attest to since I was a little kid during the war and did indeed take note of such un-P.C. material.) He refuses to hire applicant Gertrude Hart (Laura Dern) because the name sounds to him Jewish. She's not.
Advised by his boss to get a pair of glasses, Newman does so and immediately draws dirty looks from his neighbors on the street and even from his mother, who berates him for not getting the rimless kind because "you look Jewish." Assumed, then, to be a Jew by the company president, he is forced to resign his job, meets Ms. Hart once again when he applies for a new job, and marries her. Noting verbal and then physical attacks against the owner of a small luncheonette, Finkelstein (David Paymer), both Newman and his new wife spend the major segment of the story insisting that they are not Jewish. After a dramatic payoff scene, they both change their tune. Listening to their words in the final moments, one can almost see Arthur Miller himself, ramrod straight in his unbending morality, taking on the forces that have often made America anything but the land of human rights.
"Focus" is a powerful, though for the most part responsibly understated and sincere diatribe against the persistence of anti- Semitism. With its reproduction of automobiles from the mid- forties and subway cars with cushions made of straw, the movie looks every bit the period piece that it is. Yet thematically, "Focus" is torn from today's headlines. Filmed in Toronto which stands in for my Brooklyn, Neal Slavin's film is an event which in its low-key style combined entertaining with didacticism so cleverly that adolescents now in high school should be taken to see it as part of their customary field trip experiences. Nor will adults be disappointed.
In his book "Chutzpah," Alan Dershowitz argues that anti- Semitism is all but dead in the U.S. I'm sure he doesn't live in yet another Brooklyn neighborhood, Crown Heights where, while somewhat dormant, the disease springs to life now and then as when a Hasidic Australian scholar visiting the country was attacked and killed simply because of his religion. Oh, anti-Semitism is alive all right, but it festers below the surface. We're not likely to find characters like former radio personality Arthur Godfrey, who had a sign on the grounds of his Florida home, "No Jews or dogs allowed," but given the right circumstances, who knows what could happen? For a current picture that deals with the subject--how an economic depression led to a rise of ethnic hatreds in Liverpool--take a look at Stephen Frears's touching picture, "Liam."
Rated PG-13. Running time: 100 minutes. (C) 2001 by Harvey Karten<EMAIL_ADDRESS>========== X-RAMR-ID: 29749 X-Language: en X-RT-ReviewID: 253538 X-RT-TitleID: 1110564 X-RT-SourceID: 570 X-RT-AuthorID: 1123
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


This article is part of my course on Compilers, Formal Grammars and Programming Languages. Up to this point we have studied:
- What is a Compiler.
- What are the several stages of the compilation process.
- What is a Formal Grammar, and several existing types of Grammars.
- A real design example of a new Context-Free Grammar, for a new Turing-complete programming language.
- What is Parsing, the second stage of compilation.
- A real implementation of a Recursive Descent Parser, made for the new programming language mentioned above.
- What is Semantic Analysis, the third stage of compilation.
You’ll find, roughly speaking, one or two articles for each of the topics above. In the course’s content you can also find other articles meant to explore related subjects and provide a better, deeper understanding of the whole theme. Check the references!
In this article, I will show and discuss my personal implementation of a Semantic Analysis module.
As you already know, to complement my theoretical studies, I decided to build a new (simple) programming language, along with its compiler. The Semantic Analysis is the third module of this Compiler, and the last of the front-end part.
Background
For the sake of understanding this article, it’s worth reviewing what we’ve already learnt about Semantic Analysis. In brief:
- It’s the third step of the Compiler, the last one of the font-end part.
- It takes care of all errors that went unnoticed through the first two steps (Lexical Analysis and Parsing).
- It’s the last one among the steps that are meant “to reject” ill-typed codes. After Semantic Analysis, we assume the code is correct, although it might not do what the developer meant!.
- The most important things it takes care of are: symbols definitions, scopes, typing.
In Lexical Analysis (as well as in Parsing), some large part of the code can be realized with standard algorithms. This is why there exist tools, such as ANTLR, that implement them almost automatically. As said before, I didn’t use any of such tools, because I think it’s worth doing it “by hand” once in a lifetime, for the sake of learning.
The beautifully complex thing about Semantic Analysis is that most of the things it does depends on the given language specification. There are several pillars that all Semantic Analysis implementations are based on, and I discussed them in a previous article. In this one, we are going to see the implementation I made of these concepts, specific for the language I designed.
Grammar and Language review
Before going further, I think it’s worth taking a minute and review the peculiarities of the Grammar I designed, and of the Language I am building. Given the nature of what Semantic Analysis has to do, is very important to understand the key concepts of the Language.
The language I designed:
- Is extremely explicit. There are almost no “implicit” instructions or assignments. I believe this encourages the developer to think more about what she writes.
- Is also compact. Although things are explicit, you don’t need to type a lot on the keyboard. The main reason for this is because types are inferred by the compiler. Yes, there’s something “implicit” after all.
- It’s compiled. Of course!
- It’s statically typed. I discussed static and dynamic typing in vast detail in a previous article. Basically, the compiler will also check that each instruction is correct from the point of view of the types. This is what C, Java, C++ do (but types are explicit there), and what Javascript, Python, Perl do not.
- It support as basic types int, float, boolean, string and list.
- It’s Turing-complete. Yes, I’ve got you covered with a conditional instruction (if) and a loop (while), as well as I/O instructions.
- It’s designed as a learning tool and benchmark. As I said, a fairly advanced assignment to complement my studies.
- Logical lines are terminated with Physical lines. In practice, this means that the developer is forced to use two given characters anytime a statement is completed. These are semicolon and newline
';\n'
, which means two logical statements can never be on the same physical line. - It lacks advanced features, such as OOP, routines, etc. which of course are very valuable additions. They are on my road map, but for the pure objective of learning the compilation process, I decided to postpone their design and implementation.
How does a source code look like, in this language? In fact, I am quite satisfied with many design choices I made. The result is a language that looks like a scripting language, but it’s compiled and statically typed. As already said, the code must be monolithic, as routines (methods, functions) are not allowed for the moment.
The easiest is to look at an example. I am going to repeat one that I’ve already shown in a previous article: given an integer $N$ (to be entered by whoever runs the code), compute the sum of all prime numbers that exist in the interval $[2, N]$. This time though, I will add some comments to highlight the semantic of the code, not just the syntax.
readInt N; // read an integer from standard input, save it in the variable N
totSum = 0; // totSum will be automatically assigned type int, inferred by the compiler
i = 0;
while (i <= N) // i and N are both integer, so the operator '<=' is well defined
j = 2; // j is assigned integer type and value 2
isPrime = True; // isPrime is assigned bool type and value True
while ((j <= i / 2) && isPrime) // the two sub-expressions have both boolean type
if (i % j == 0)
writeOut "%d is not prime", i; // write on standard output
isPrime = False;
;
j = j + 1; // assignment, the left-hand side is an integer, so it's the right-hand side
; // this is the end of the logical line started with "while"
if (isPrime)
totSum = totSum + i; // totSum+1 has type int (inferred) so can be assigned to the
// variable totSum
;
i = i + 1;
;
writeOut "Total primes sum until %d is %d", N, totSum;
Tasks for Semantic Analysis
Let’s now discuss what tasks Semantic Analysis should accomplish for this language. When I arrived at this point, I literally asked myself the question - what errors can still be uncaught?
Assignment Statements
I started off by thinking about the assignment. After all, assignment statements are some of the most common instructions in a source code, of any language. I went back to the Grammar definitions and found it:
assign : var '=' expr
I knew that the Parser would take care of checking most issues there:
- It would check that the first Token really is a
var
Token. - Then, it would check there is an Equal Symbol (that’s a Token too).
- It would also check that after the Equal there is a well formed
expr
, made by a potentially very long sequence of Tokens, or even by just one Token.
What’s left? There are a few things Semantic Analysis has to do, still.
- It must understand what is the type of the whole
expr
Token. - If the Symbol contained in the
var
Token (also called lexeme) was never defined before, then it must be added into the Symbol Table. To know what such a Table is, I recommend checking my previous articles (see the references at the end of this one).- It should also assign to this Symbol the type computed at step 1. This information must be saved somewhere in memory (somewhere linked to the Symbol Table, of course).
- If the Symbol in Var was already defined then things are quite a bit different.
- Optionally display a warning that a variable has been overwritten. I would not do this at this stage though (and I will explain why in a minute).
- Check what was the previous type assigned to such Symbol, in the Symbol Table.
- If the type found in 3.2 is not the same as the type computed at step 1, then two options are possible:
- Reject the code with a compilation error.
- Overwrite the type of that Symbol, in the Symbol Table. In this case a warning message is also opportune, in my opinion.
The point I discuss in 3.3 is very important. In fact, I initially decided to go with the option 3.3.2, because I wanted to give the developer the possibility to modify the type of a variable.
However, I later changed my mind and went for 3.3.1. That means that now you cannot modify the type of a variable after it’s defined the first time, in my language. This is also what happens in C and Java, for instance. Why did I do that? The problem is that option 3.3.2 clashes with my ideas on how to handle List objects, as we’ll see in a minute.
Overall, this task is not very complex, assuming that the first step (understanding the type of a whole Expression) is already solved.
Pseudo-code to descend the Parse Tree
The concept I want to discuss is well shown in the following pseudo-code:
function analyzeNode (Node n, SymbolTable table, Scope scope) {
preprocessNode(table, scope, n);
analyzeNode(n.child);
postprocessNode(table, scope, n);
}
This code seems not doing anything at all, but in fact it shows the core principle of how to execute Semantic Analysis in complex cases such as the Expression.
First of all, remember that when we want to analyze some complex structure what we really have access to is the root node of the subtree, within the Parse Tree, that was created by the Parser.
We therefore start the analysis at such node. As the code perfectly clarifies, we “just” do three things: some pre-processing for this node, the analysis of the child, and some post-processing.
The key here is that the function analyzeNode
is recursive, of course. By calling it over and over for each child, we will eventually arrive at the leaves of the tree. Leaves are very simple Token Types, therefore understanding their semantic is extremely easy. Moreover, at the leafs there’s usually no need to pre-process or post-process anything.
Let’s look at one example that clarifies everything.
A leaf can be, for instance, a num
Token, which is either a float
or an int
. I want to show you the code I used to analyze a num
node in my Semantic Analysis. Although you don’t have yet the full picture, its simplicity will be evident.
int analyze_Num (struct ParseTree *tree) {
struct ParseTree *num;
num = tree->child; // the Float node
if (num->data->type != Float)
// it's the sign, skip it
num = num->sibling;
if (num->child->data->type != Int)
return _float;
if (num->child->sibling != NULL)
// then there is either frac or pow
return _float;
return _int;
}
All I do in the code above is to check the shape of the subtree that starts at the num
node (the pointer given as argument to the function), and return the type of it.
The literals _int
and _float
are constants that I defined (with the #define
instruction in C). parseTree
, floa
, int
are all struct definitions or Token Types I defined in the Lexical Analyzer or in the Parser.
How did I know the structure of the subtree? I simply looked at the Grammar.
num : ('+' | '-')? float
float : (frac exp?) | (int frac? exp?)
int : '0' | digit+ digit0*
If you carefully analyze that portion of the Grammar side by side with the analyze_Num
function, you’ll see things more clearly.
Now, imagine that we are analyzing an Expression. We’d keep initiating recursive calls following the pre-process, analyze-child, post-process strategy. But when we arrive to a Num node, the recursion will stop because the function analyze_Num
will simply return the type of the Num subtree.
You are probably thinking - wait! The Num subtree is not a leaf, why aren’t we descending further with more recursive calls?
Even though you are formally right, there’s no reason to pile up unnecessary recursive calls. Even though num
is not formally a leaf, it’s simple enough that we can analyze it directly.
This is all about “analyzing” a Node: either call the same function recursively on its child (or children), or just return the type of that node. The latter works for simple nodes.
What about the pre-process and post-process functions? The actual steps you have to take in these functions depends on the type of Node you are currently analyzing, as well as the overall language specification. Here’s some things that could be required:
- Push information into the stack of Scopes (pre-process).
- Pop information from the stack of Scopes (post-process).
- Push information about the Context (pre-process).
- Pop information about the Context (post-process).
- Add a new Symbol in the Symbol Table (pre-process, usually).
In fact, there are many other things that can potentially be done. I can’t really offer a universal recipe about this, but I will show you what I did in my Semantic Analysis implementation.
For the moment being, I want to give one example that would help clarify. My Grammar supports the continue
and break
instructions. Their semantic is the same as in many other languages: to exit from the innermost loop, or conditional (if
) statement.
There’s a catch with these instructions. They can only appear inside a loop or a conditional block. For example, the following code is correct
while (x <= 5)
writeOut "OK";
break;
;
Whereas the following one isn’t, and should be rejected.
while (x <= 5)
writeOut "OK";
;
break;
This is a perfect example of information that can be pushed onto a stack in the pre-processing stage of a Node, before going further down in the recursion. In my case, I handle these situations by simply pushing a flag that says the current Context allows for break/continue instructions. Then, I pop this flag from the Context in the post-processing stage.
Let’s go back to the analysis of the most interesting piece of Grammar: the Expressions.
Expressions
In my programming language Expressions have a complex, recursive definition very typical of Context-Free Grammars. I have explained it in great detail in my article about the Grammar (again, see the references at the end).
What has Semantic Analysis got to do about them?
- It must check that every Symbol used within the expression was defined earlier in the code.
- It must check that every operator in the expression is used with compatible types.
- It must compute the final return type of the entire expression.
Let’s go with three examples, one for each point above.
x = 3;
y = x + z;
Clearly, the two lines above should not compile, because the symbol z
, used in the expression to assign a value to y
, was never defined.
x = 3;
z = "abc";
y = x + z;
The three lines above should also generate a compilation error. The reason is that the operator +
is used with a int
type (x
) and a string
type (z
). Even though this kind of operation may be allowed in some languages, the semantic of my language forbids it. It was my choice, of course.
x = 3;
z = "abc";
y = z + "%d", x;
These three lines should be compiled correctly. No error should be reported. Moreover, the Symbol y
should be assigned type string
. Why? Because Semantic Analysis must be able to understand that the result of the expression
z + "%d", x
is a string. This, of course, under the condition that the operator +
is well defined between two strings.
How should we go about implementing that? Here’s where the previous digression about pseudo-code and analysis strategy kicks in.
Every expression is analyzed with multiple recursive calls, that descend into the Parse Tree until a leaf, or a simple subtree is found. In my code, some examples of these are:
- The Num Token, as we already saw.
- The Var Token. In this case, the string literal of the Token (formally called lexeme) is searched in the Symbol Table. If found, its type is returned. If not found, an error is reported.
- Int, String, Bool, Null, Float and ListElem Tokens. Notice that Int and Float are actually always nested into Num.
Thus, all recursive calls will eventually stop when any of those Token Types is found. Then, the result will be returned by the function that analyzed them. You can imagine the procedure as to descend into the Parse Tree first, and then climb up to higher levels carrying the results computed at the bottom.
While climbing up and carrying the results from the lower levels, all sorts of checks are performed. For example, consider the simple expression
3 + "abc"
At the bottom of the Parse Tree the recursive call would stop:
- On the left side of the tree, when the Num subtree that contains the
int
Token with value3
it’s met. In this case, the type_int
will be returned. - On the right side of the tree, when the String subtree that contains
"abc"
is found. Here, the_string
type will be returned.
These two results will be carried over while climbing up the tree. The algorithm will then meet the Node that contains the operator +
. Here, it will check if such operator is valid. In this specific example, an error message will be generated because the +
is not defined (in my language) between int and string types. The source code that contains that expression will then be rejected.
No matter how complex the Expression is, or, that’s the same, how many nested levels there are in the subtree for this Expression. The general strategy does not change by an inch.
Lists
List is a data structure that I really wanted to add in my programming language. First of all, because containers help to write readable source code. Secondly, because I find the notation à la Python quite beautiful and handy. Thus, my language supports statements such as
x = [1, 2, 3]
However, the semantic Lists have in my language is more similar to the typed arrays in C and Java, than to actual Python lists. Let me explain better.
In my professional experience, where I use Python a lot, I’ve seen that many developers use lists (and tuples) with mixed types. For example:
x = [1, "string", {'a': 'dict'}]
Now, even though this is valid in Python, and perhaps in some cases can lead to more compact code, and everything works nicely in your code, I discourage this type of code. In my humble opinion, it’s bad practice to mix different types in the same container.
This is why I decided to forbid that in my language. If you try to do it, the Compiler will reject your code!
Who’s taking care of checking it? Semantic Analysis, of course! Here’s how it works.
First, when the root of the subtree containing a List is found, Semantic Analysis skips the initial bracket [
. Why? We know it’s there, because the Parser already checked it.
Then it comes the actual list content. Now, thanks to the Grammar we know that objects in the list are comma-separated.
list : '[' (listExpr)? ']'
listExpr : obj (',' obj)*
Thus, the function that analyze the listExpr subtree will analyze object by object, skipping the commas. What does “to analyze a obj Token” consist of? Let’s look at its definition
obj : var | num | str | bool | null | list | listElem
Therefore, we would simply switch among those token types. Notice that they are all very simple Token Types, precisely those types that do not require recursive calls.
After each object in the listExpr
has been analyzed, the Semantic Analysis checks that all of them have the same type:
- If not, then report an error and reject the source code.
- If yes, then save this information somewhere linked from the Symbol Table. The reason is that we must know what type of objects a list contains. This is actually how the type for the basic Token listElem is found.
Let me repeat again the second point above. Say we are analyzing the following expression
x = [1, 3, 6]
When the list on the right-hand side will be analyzed, we know that it’s a valid list of integers. Thus, we must save two information in the Symbol Table (and in the current scope):
- The Symbol
x
refers to alist
type. - The list referred by
x
contains allint
types.
Why is point 2 important? Because in future parts of the code we could find a listElem
Token, for example
y = 3 + x[1]
And we must have a way to check what’s the type of the elements inside the list x
, so we can decide whether 3 + x[1]
is a well-typed Expression or not.
At this point it should also be clear why I decided to forbid to change a variable type after it’s defined the first time. If that was allowed, then it would be easy to mess up with containers, for example
x = 3; # x is int
y = 5; # y is int too
z = [x, y]; # z is a list of int
x = "ooops"; # a string! Now the list is mixed up.
Similar case will be handled by Semantic Analysis, which will reject the code. Note, however, that I can’t stop you from writing weird code, if you really want: the following code is valid, but strongly discouraged.
x = [1, 2]; # list of integers
y = ["a", "b"]; # list of strings
z = [x, y]; # list of lists, where inner lists have different types
However, since I don’t support double indexing in the Grammar (such as z[0][0]
), this should have limited effects. At any rate, just don’t do it!
Basic Operations
The type of checkings Semantic Analysis will do most often is the basic check about correct usage of an operator. For example, when it finds the subtree relative to code such as
if (x + 3 <= y)
it will have to decide (among many other things) whether the operations +
and <=
are valid.
Why did I say this is the most frequent type of check? Simply because Expression is the most frequent Token Type you will find in computer languages, not only in mine. Here’s a partial lists of where it’s used:
- Assignments (
var = expr
) - Conditionals (
if (expression) do something
) - Loops (same logic as conditionals)
As we have seen in the previous subsection, the semantic evaluation of an Expression eventually boils down to two steps:
- Understand types of basic objects involved (
x
,3
, andy
in the previous example). - Decide if the operators between these objects are well used. For example, you cannot use
+
between aint
type and astring
type, in my language.
And this is why to check basic operations is a task that Semantic Analysis will perform a lot.
How to go about it? Strictly speaking, this is an easy type of reasoning. All we have to do is to check, for each operator, if the two operands have types that can be used with that operator. Theoretically, this corresponds to a nested sequence of if/then/else.
if (operator == '+')
if (operand1.type == "int")
if (operand2.type == "int")
return VALID;
if (operand2.type == "float")
return VALID;
if (operand2.type == "string")
return FAIL;
// many more...
However, this type of implementation is quite silly:
- It’s slow. Every time we want to check an operation we have to go through the evaluation all these nested conditions.
- It’s verbose and error-prone, as every bad code ever written.
The much better solution, perhaps the best, is to use lookup tables. The idea is to have a lookup table for each operator, implemented as a 2-dimensional array. The row and column index correspond to the type of operand1 and operand2.
I am going to illustrate this much more in detail in the next section, for now let’s just grasp the idea. Here’s a snippet from my code.
#define _int 0
#define _float 1
#define _string 2
#define _bool 3
#define _null 4
#define _list 5
#define _undef -100
// ...
int plusOperatorLookup[6][6] = {
/* int float string bool null list */
/* int */ { _int, _float, _undef, _undef, _undef, _undef},
/* float */ { _float, _float, _undef, _undef, _undef, _undef},
/* string */ { _undef, _undef, _undef, _undef, _undef, _undef},
/* bool */ { _undef, _undef, _undef, _undef, _undef, _undef},
/* null */ { _undef, _undef, _undef, _undef, _undef, _undef},
/* list */ { _undef, _undef, _undef, _undef, _undef, _undef}
}
To see how this works, let’s get back to the simplest example of expression
y = x + 2;
We already know that Semantic Analysis will evaluate this assignment statement by evaluating the right-hand side (after the =
) sign, which is an expression.
It will walk down to the leafs of the Parse Tree, via recursive calls. The branching will stop in two places:
- When it finds the
var
Token, forx
, it will use a function probably namedanalyze_Var
. Such function does not start any recursive call, because to analyze avar
Token is a simple enough task, as we saw earlier. Let’s assume thatx
was already defined in the Symbol Table (so the code is correct), and it’s type is_float
. - When it finds the
num
Token, for2
. We already know what happens in the functionanalyze_Num
. In this case, it will return_int
.
Now that we have got the two results _float
and _int
, the magic happens. It will simply call
int result_type = plusOperatorLookup[_float][_int];
Notice that _float
and _int
are defined as integer value corresponding to the correct indexes of the lookup table! A small, but very useful trick. The above operation is very, very fast.
Furthermore, notice that the lookup table gives one more information, not just whether the operation is valid or not. The lookup table tells us what the result type is.
For example plusOperatorLookup[_float][_int]
gives the type _float
. In fact, if you do 3.2 + 4
you want the result to be stored in a floating point object (7.2
, hopefully!).
Finally, notice also that I defined one more constant value, _undef
, that is returned when the operation is not valid. For example, we would get _undef
from plusOperatorLookup[_null][_int]
, because operations such as 3 + NULL
are not valid, in my language as well as in many others.
I defined more lookup tables like that, although not one for every and each operator. The reason is that the same rule applies to more than one operator.
For example, the same lookup table works well for +
, -
, *
, /
. Another table works for comparison operators, such as <=
, <
, >
, >=
. And so on, I grouped operators together and defined only the strictly necessary lookup tables.
Code Organization
In the previous section you saw the main items on the list what does Semantic Analysis has to do? You’ve also seen that the answer is very specific to the Grammar and the Language you’re building the compiler for.
With this information, you are now able to implement your own Semantic Analysis module. Nonetheless, I want to show more details about my implementation, so you can get a more tangible perspective of what my code looks like, and possibly give me some good suggestions.
As you know, my whole Compiler is implemented in C. I created the header file semantic.h for the Semantic Analysis part. First of all, I defined some constant for the types (that we already saw), and for error messages.
#define _int 0
#define _float 1
#define _string 2
#define _null 3
#define _bool 4
#define _list 5
#define NODE_OK 100
#define _undef -100
#define UNDEFINED_SYMBOL -1
#define NODE_TYPE_ERROR -2
#define LIST_TYPE_ERROR -3
#define SEMANTIC_ERROR -4
#define BREAK_OUT_OF_CONTEXT -5
#define CONTINUE_OUT_OF_CONTEXT -6
#define OVERWRITE_TYPE_ERROR -7
The constant NODE_OK
is meant to signal that the analysis of an entire Node (that is, a subtree) went fine, in case we do not have to return a type.
The above sentence deserves more details. The points is that, even though the algorithm to analyze any subtree is pretty much always the same, the conclusions of such analysis can be threefold:
- A simple
NODE_OK
value, that is like saying “This subtree is OK, go ahead with the analysis”. - An error message (will be discussed in a second).
- An actual type. This is the case, for example, for subtrees that represent Expressions. The analysis must return the type of that Expression subtree, if it’s well-typed of course.
Thus, the negative constant values I defined are meant to represent different error types
For example, the constant BREAK_OUT_OF_CONTEXT
will be returned when Semantic Analysis find a break
keyword used outside of a loop or a if/else.
LIST_TYPE_ERROR
is used when the objects in a List Token do not have all the same type.
SEMANTIC_ERROR
instead is a generic error returned in several cases. OVERWRITE_TYPE_ERROR
is when you try to change the type of a variable, by redefining it.
The next things I defined in the header file are the lookup tables for the basic operations. I have four of them:
resultType_aritm
. This is for the operators+
,-
,/
,*
,%
.resultType_floatDiv
. This is for the operator/.
that means float division in my language.resultType_compare
, for<
,>
,<=
,>=
.resultType_logic
, for&&
,||
,!=
,==
.
After this, the next step was to define the data structures that I will use. I will not discuss in too much detail what data structures are typically used for Semantic Analysis as I illustrated that in great detail in my previous article (see the references at the end).
Here’s what I needed to use:
- A Symbol structure.
- A Symbol Table, that keeps references to a collection of Symbol structs.
- A Stack of Context objects. I will explain this in a moment.
In general though, with complex languages and especially OOP languages, you will also need a Stack of scopes, where each scope is intended like real scopes defined by language elements. For example, each method in a class defines its own scope. A class has a scope that contains more scopes (one for each method, for example). And then there’s also the global scope, with the variables that are visible in all parts of the code. Each of these scopes need to have its own Symbol Table. My Grammar is very simple, and therefore there exists only a global scope.
What about the data structure I called Stack of Context? The motivation for it lies in tracking down the correct usage of keywords such as break
and continue
: we need to make sure they are used only within a loop, or a if/else statement.
The easiest way to do this is to keep a pointer to a stack-like data structure, where information about the current context is pushed on the top, or popped from the top. This is exactly the definition of stack in computer science.
Thus, when we enter a loop in the source code, I would push on the Context Stack this information. Then, when we leave the loop, I would pop from the stack. If we enter a if/else before leaving the loop, I would push that information too, onto the stack. So, if the code is well written, we would first leave the if/else (one pop from the stack), and then leave the loop (another pop). At any moment, if a break
or continue
keyword is found, I would check what’s the context at the top of the stack, and if it’s not a loop or a if/else then I would return an error value.
After all, the information we need in the Context is entirely contained in the TokenType structure, defined a long time ago when I implemented the Lexical Analysis, in the header file lexer.h. Once more, I can only recommend to check out previous articles of this series.
Here’s how the Context Stack is implemented.
struct ContextStack {
enum TokenType top;
struct ContextStack *next;
};
And here are the operations it supports:
include parser.h // it includes lexer.h
struct ContextStack* alloc_Context(); // create
void free_Context(struct ContextStack *stack); // free memory
void push_Context(struct ContextStack **stack, enum TokenType type); // push on the top
enum TokenType pop_Context(struct ContextStack **stack); // pop from the top
void print_Context(struct ContextStack *stack); // print at screen
Regarding Symbol and Symbol Table, here’s how I implemented them. Just keep in mind that a clever solution for the Symbol Table is to implement is as a Hash Map. The reason is that we will have to perform a lot of searches in this table; at any rate I discussed this subject, as well as alternative implementations, in the previous article.
Since my focus wasn’t on implementing a great hash function (that, by the way, is a very interesting task and one that is worth studying in depth), I decided to keep it simple and used a very standard linked list.
struct Symbol {
char *sym;
int type;
int list_type; // type of each element if list
};
struct SymbolTable {
// currently implemented as a linked list
struct Symbol *head;
struct SymbolTable *next;
};
Note that each Symbol structure keeps track of both its own type, as well as the type of the objects it contains in case it’s a list. We saw a lot of Linked List-like data structure in the previous articles, so I will not discuss it further at this time.
The entry point of Semantic Analysis is also specified in the header file semantic.h, and it’s the following function
int analyze_Program(struct ParseTree *node);
The argument node is assumed to be a pointer to the root of the entire Parse Tree that was built by the Parser. The whole thing, not a subtree.
Switching to the actual implementation (the file semantic.c), let’s start by seeing the analyze_Program function.
int analyze_Program(struct ParseTree *node) {
struct SymbolTable *table;
struct ContextStack *stack;
int res;
table = alloc_SymbolTable();
stack = alloc_Context();
res = _analyze_Program(node, &table, &stack);
free_SymbolTable(table);
free_Context(stack);
return res;
}
int _analyze_Program(struct ParseTree *node, struct SymbolTable **table, struct ContextStack **stack) {
struct ParseTree *line;
int status;
int res;
line = node->child;
status = _undef;
res = NODE_OK;
while (line != NULL){
status = analyze_Line(line, table, stack);
if (status < 0){
printf("ERROR: %s\n", type2str(status));
res = SEMANTIC_ERROR;
}
else
printf("OK. Type is %s\n", type2str(status));
// Skip Endline
line = line->sibling->sibling;
}
return res;
}
Basically, the entry point analyze_Program
is just an interface function that creates the data structure we will need along the process (SymbolTable and ContextStack) and then calls the internal function _analyze_Program
.
This internal function has a very simple behavior. It takes each Line node, child of the root node (that is Program TokenType), and calls the internal function analyze_Line
for each of them. Notice that Endline Tokens are skipped, because we know the Parser already checked they are there.
Let’s now take a look at the analyze_Line
function.
int analyze_Line(struct ParseTree *node, struct SymbolTable **table, struct ContextStack **stack) {
struct ParseTree *line;
int res;
line = node->child;
if (line->data->type == Assign)
res = analyze_Assign(line, table);
else if (line->data->type == IfLine)
res = analyze_IfLine(line, table, stack);
else if (line->data->type == Break)
res = analyze_BreakLine(line, table, stack);
else if (line->data->type == Continue)
res = analyze_ContinueLine(line, table, stack);
else if (line->data->type == Input)
res = analyze_Input(line, table);
else if (line->data->type == Output)
res = analyze_Output(line, table);
else if (line->data->type == LoopLine)
res = analyze_LoopLine(line, table, stack);
else
res = SEMANTIC_ERROR;
if (res < 0)
return res;
else
return NODE_OK;
}
In this function, I quite simply identify the type of Line that is currently under analysis, and invoke the right function.
One point I want to drive your attention on is that all functions named analyze_XYZ
have similar signatures, and they call each other depending on the current Token Type.
Let’s keep digging deeper, and have a look at the analyze_Assign
function. Like its name says, this function will be invoked when a Token assign
is found. It’s worth recalling once more that this kind of Line is grammatically defined as
assign : var '=' expr
You will see that the code uses this definition.
int analyze_Assign(struct ParseTree *node, struct SymbolTable **table) {
struct ParseTree *var, *expr;
int found_var, valid_expr;
struct Symbol *sym;
// Get the part of this subtree we are interested in
var = node->child;
expr = var->sibling->sibling;
found_var = analyze_Var(var, table);
if (found_var == UNDEFINED_SYMBOL)
// the add_symbol function prints a log message
// and add the symbol in the table
add_symbol(table, var->data->lexeme);
sym = search_symbol(*table, var->data->lexeme);
valid_expr = analyze_Expr(expr, table, &sym);
if (valid_expr < 0){
printf("Expression is not valid\n");
return valid_expr;
}
if (sym->type != _undef && valid_expr != sym->type){
printf("ERROR: Cannot Modify Type for Identifier %s to %s. It was %s.\n",
var->data->lexeme, type2str(valid_expr), type2str(sym->type));
return OVERWRITE_TYPE_ERROR;
}
assign_type(table, var->data->lexeme, valid_expr);
return valid_expr;
}
After all, this function is quite easy too. It gets pointers to the subtree that contain the Var and Expr parts of the Assign Line, then it calls the function _analyzeVar and _analyzeExpr. I am sure you start getting the pattern by now.
Let’s keep walking down the tree, and look at the analyze_Var
function.
int analyze_Var(struct ParseTree *node, struct SymbolTable **table) {
struct Symbol *found;
found = search_symbol(*table, node->data->lexeme);
// found contains the _type of the symbol, or UNDEFINED
if (found != NULL)
return found->type;
printf("Variable Symbol Not Found In Symbol Table: %s\n", node->data->lexeme);
return UNDEFINED_SYMBOL;
}
And so we see one case where the recursive calls end. The function analyze_Var
simply checks if the symbol contained in the current Node was already defined. If yes, it returns its type. If not, it returns the error value UNDEFINED_SYMBOL
.
Let’s briefly turn our attention to the function analyze_Expression
, that I discussed in detail in a section above. We can thus see how the theory is implemented into code.
Recall that the expressions are defined in the Grammar with a recursive rule:
expr : pred (condOp expr)?
pred : term ( ('+' | '-') pred)?
term : baseExpr ( ('*' | '/' | '/.' | '%') term)?
baseExpr : obj
| '(' expr ')'
You will see that the code leverages on this structure quite a lot, and uses functions such as analyze_Pred
, analyze_Term
, analyze_BaseExpr
.
int analyze_Expr(struct ParseTree *node, struct SymbolTable **table, struct Symbol **sym){
struct ParseTree *child, *op;
int type1, type2, result;
child = node->child; // the Pred Token
type1 = analyze_Pred(child, table, sym);
if (type1 < 0){
printf("Sub Expression Ill-Formed ");
if (sym != NULL)
printf("For Symbol: %s\n", (*sym)->sym);
else
printf("\n");
return type1;
}
if (child->sibling == NULL)
// then this expression is completed
return type1;
// Save the operator, skip it for now
op = child->sibling;
// Analyze the second part of this expression
type2 = analyze_Expr(op->sibling, table, sym);
if (type2 < 0){
printf("Sub Expression Ill-Formed ");
if (sym != NULL)
printf("For Symbol: %s\n", (*sym)->sym);
else
printf("\n");
return type2;
}
// Now compute the result type with the lookup tables
// based on the operator previously saved
if (is_ComparisonOp(op->data->type))
result = resultType_compare[type1][type2];
else if (is_LogicOp(op->data->type))
result = resultType_logic[type1][type2];
else
result = NODE_TYPE_ERROR;
return result;
}
I think I explained the entire logic in a previous section (see Tasks for Semantic Analysis - Expressions), so I will let you connect the dots!
Take-home Messages
If you made it so far, and you also read other articles, you have now got a good grasp on all concepts around Semantic Analysis. In the past articles I discussed a lot of theoretical details, whereas in this article we saw many practical details and implementation tips.
 Remember that:
- You’ll need data structures such as Symbol Tables, Scopes/Context and Stack.
- Your algorithm is going to be heavily recursive.
- You should identify the places where the recursion will end. These are usually very close to the bottom of the Parse Tree.
- You can take a look at my own implementation, but don’t be afraid to experiment and strive for further optimization. Focus on learning the concepts though, without spending time on “irrelevant” details. Irrelevant for the sake of learning, of course.
Summary and Outlook
You are now able of building your own front-end Compiler!
Semantic Analysis is indeed the last module in what’s usually called front-end compilation process. The previous two are Lexical Analysis and Parsing.
We have studied the three of them in great detail, both theoretically and practically. Therefore you can take what you’ve learnt and put it into practice.
After this, the path towards building a new programming language and its Compiler is waiting for one more milestone only: Code Generation.
We have already studied Code Generation at the theoretical level, and in the next article I will show how I put those concepts into practice and built my own Code Generation Module.
References
My GitHub repository for this course.
Table of contents for this course.


I am working on setting up a new system for publishing content. I have a few different categories of content that I’m interested in creating. I’ll have to determine exactly what the taxonomy will be, but the broad categories will probably be computers, mountain biking, and more personal stuff including relationships and religion. The first step towards this new system is just to replace the technology behind this website.
This website is currently generated statically using a very old version of jekyll/octopress. Static site generation is really nice, but I think I’m going to want to add some more interactive features like small applications. Therefore, I decided to replace this static site generation approach with a Clojure application.
Since these posts currently are all written in markdown and then parsed and rendered into HTML before being served statically via nginx, I wanted to check to see how expensive it would be to parse and render the markdown into HTML on every page load. To evaluate, I used a couple of handy Clojure libraries – markdown-clj and criterium. Using markdown-clj
it was fairly trivial to replicate the functionality of the markdown processing of octopress. It is even has the ablility to parse the metadata at the top of the markdown files. For example, this is the metadata that I have at the top of this post:
1 2 3 4 5 6 7 |
|
To parse that metadata, I simply had to pass in the :parse-meta? true
option when parsing, like this:
1
|
|
Then the metadata is parsed nicely into a map for me:
1
|
|
You can see more detail in the source code on github.
Finally, I created an uberjar using lein uberjar
, uploaded it to the DigitalOcean machine I intend to use, and ran the benchmark using criterium:
1
|
|
Because of this issue, I also had to call flush
afterwards to get the output to display correctly. Again, you can see more detail on github.
Once I ran the benchmark, criterium gave me some useful results:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
I can see there that it takes about 20ms to parse a typical markdown file for one of my blog posts. That would mean that, ignoring other overhead for serving a webpage, I could serve about 50 pages per second. That seems more than acceptable for the amount of traffic I expect to receive on this blog.


Hi! To find more instructions on how to navigate this template of code, if you haven't included ArchieML support (this pulls specifically-formatted text from a Google Doc with shared settings of "Anyone with the link can view"), then add ArchieML support to this project for a copy of this Google Doc that is appropriately shared. Or if you've added Archie configuration and provided a doc id, then in terminal, exit out of the current process and run `gulp archie`.
{% for section in ARCHIE.sections %} {% include '_sections/' + section.type +'.html' %} {% endfor %} {% include "partials/_breakpoints.html" %}


Arabic Alphabet Flashcards
Game Controls
Difficulty
Basic
Advanced
Enable vowels
Game Type
Transliteration of character
Character of transliteration
Character to sound
Initial form of contextual form
Character form of transliteration
Character form of audio
Card
Choose an answer


Breaking News: Cat does not give a damn
This paragraph will include the photo of a random cat that the author of this tutorial has found online. You can replace this text with any random text. The sole purpose of this copy is to fill the space and make sure that the image to the left has enough text to low around it. I even decided to copy the previous paragraph. This paragraph will include the photo of a random cat that the author of this tutorial has found online. You can replace this text with any random text. The sole purpose of this copy is to fill the space and make sure that the image to the left has enough text to low around it.
This paragraph will include the photo of a random cat that the author of this tutorial has found online. You can replace this text with any random text. The sole purpose of this copy is to fill the space and make sure that the image to the left has enough text fo low around it.


Preparation time
less than 30 mins
Cooking time
30 mins to 1 hour
Serves
Serves 2-3
Sweet and sticky with crisp skin, this recipe makes the most of chicken thighs.
Preheat the oven at 200C/400F/Gas 6.
Place the peppercorns into a pestle and mortar and grind until roughly crushed. Add these to a large bowl together with the lemon juice, honey, mustard and garlic and mix well.
Place the chicken thighs into a large roasting tin and pour the lemon and honey mixture over the chicken, leaving it to marinate for as long as possible. Sprinkle with sea salt, to taste, then cook in the hot oven for 45 minutes, turning halfway through cooking so that the thighs become lovely and sticky.
Meanwhile, cut the preserved lemons open and remove the soft flesh to leave you with just the skin (discard the flesh). Cut the skin into strips and toss together with the olives and parsley. When the chicken is ready, serve sprinkled with the olive, parsley and preserved lemon mixture.


I’m not running for another term, so I can afford to be reckless – Buhari
by Emmanuel AdigwePresident Muhammadu Buhari has said that he “can afford to be reckless because” he would not be needing the votes of Nigerians again in another election.
He stated this on Friday during the National Executive Committee meeting of the All Progressives Congress in Abuja, Nigeria’s capital and he disclosed that apart from the fact that age was no longer on his side, he would not seek a third term in office because it was not backed or supported by the Nigerian constitution.
Buhari said: “I am not going to make mistake of attempting a third term or whatever term.
“Besides age, I swore by the holy book that I believe in and will go by the constitution.
“I know I am in my last term and I can afford to be reckless because I am not going to ask for anybody’s vote.”
Previous Post
Buhari receives NIPSS Report on Universal Healthcare, pledges action
Next Post
NSE All-Share Index rises by 0.44%


Design web pages with CSS
CSS treats each HTML element like it is it's own box and the rulles you write will be applied and tells it how it shoulld look.
There are selectors - specify the elements that the rule applies to,
and declarations - that indicate what the elements should look like.
Declarations have two parts - properties of the element that you want to change and the values of those properties.
CSS rules should be their own page and reference it in the HTML file.


Download and installation¶
The current release is version 2.0pre.
Packaged versions¶
You can download it from the Python Package Index. For installation of packages from PyPI, we recommend Pip, which works on all major platforms.
Under Linux, most distributions include a package for Pygments, usually called
pygments
or python-pygments
. You can install it with the package
manager as usual.
Development sources¶
We’re using the Mercurial version control system. You can get the development source using this command:
hg clone http://bitbucket.org/birkenfeld/pygments-main pygments
Development takes place at Bitbucket, you can browse the source online here.
The latest changes in the development source code are listed in the changelog.


3 writes to IsNetworkDrive
System.Management.Automation (3)
namespaces\FileSystemProvider.cs (3)
555
drive.
IsNetworkDrive
= true;
683
drive.
IsNetworkDrive
= true;
1118
newPSDriveInfo.
IsNetworkDrive
= true;
2 references to IsNetworkDrive
System.Management.Automation (2)
engine\SessionStateScope.cs (1)
194
if (drive.
IsNetworkDrive
)
namespaces\FileSystemProvider.cs (1)
741
if (drive.
IsNetworkDrive
)


In the first part I built the foundation for a protocol oriented network abstraction written in Swift. The main focus for the component lies on safety, code quality and a very clean API.
Safety is mostly about the rules you define on how the component can be used. In the best scenario the user can not even compile the program if the component is configured wrongly. Of course, this is the perfect case which is just not reachable. But by defining different protocols for different http methods, it is possible to distinguish between them on the level of Swift’s type system instead of comparing Strings.
Code quality is a very generic term and I bet that everyone will think differently about this. In my eyes code quality is defined by readability and the structure of the code. A rule of thumb is that the code is written in 10% of the productive time but it is read in 90% of it. That means you are fighting with yourself when writing ‘spaghetti code’. Related to the rest component building code quality means to structure the code that a user could easily fix a bug by himself.
API design is a subset of code quality since it defines how the interface of the component is built. Even while there should be documentation it should not be necessary to read it to be able to use the code. It is also bound to safety in this case because the API should be strongly typed though generics since the concrete types are not even defined in this module.
So, what does the API of the client look like?
public class Client {
public enum Errors : Error {
case invalidUrl(String)
case invalidResponse(Data?, Error?)
case requestFailed(Int, Error?)
}
public init(baseUrl: String, authenticator: Authenticator, timeout: TimeInterval = default)
public typealias Completion<R : JSONObject> = (Response<R>) -> Void
public func get<E : GET>(_ endpoint: E, completion: @escaping Completion<E.ResponseType>)
public func post<E : POST>(_ endpoint: E, completion: @escaping Completion<E.ResponseType>)
public func put<E : PUT>(_ endpoint: E, completion: @escaping Completion<E.ResponseType>)
public func delete<E : DELETE>(_ endpoint: E, completion: @escaping Completion<E.ResponseType>)
}
First of all, there are some Errors defined via a nested enum. That is very convenient since they are bound to the namespace Client
. There is one initializer which takes a baseUrl, an authenticator which I will describe in a moment and a timeout in seconds. Those three values are also stored in properties which might also be part of the interface but I removed them from this view for clarity.
The rest of the API are methods for each possible http method. Since every method that starts a request takes a generic endpoint it forces via the type system that only endpoints can be used that support the given http method.
To make this more clearly, think about this arbitrary endpoint:
struct MessageEndpoint: POST, DELETE {
typealias ResponseType = Message
let path = "message"
}
This endpoint describes the message service of our random backend. It is possible to POST (add) a new message or to DELETE an existing one. This is realized with the multiple inheritance via protocols. And since MessageEndpoint
does not conform to GET
, it is not possible to use it with the get
method of Client
. That is safety enforced by the compiler.
In the next blog post I will tell more about the associated type in the Endpoint
definition. But before that I would like to quickly describe the very basic authentication implementation:
public protocol Authenticator {
func authenticate(request: inout URLRequest)
}
An Authenticator
is a type that is able to authenticate a given request. It does not matter for the client how this is done, it is just important that the correct header values are set. So before sending the actual request, the client gives its authenticator the chance to authenticate the request. Here is a very basic implementation of an authenticator:
public struct SimpleAuthenticator: Authenticator {
let authenticationBlock: (inout URLRequest) -> Void
public func authenticate(request: inout URLRequest) {
self.authenticationBlock(&request)
}
}
This simple struct wraps a closure which is called to authenticate a given request. For the Github API this is enough since we use app tokens to authenticate us with the server. So when using the SimpleAuthenticator
the code looks like this:
let authenticator = SimpleAuthenticator { req in
req.setValue("token \(githubToken)", forHTTPHeaderField: "Authorization")
}
But since the Authenticator
is declared as a protocol it is also possible to implement very complex authentication algorithms. The authenticator gets the complete request with all information which he could use to calculate and manipulate.
Thanks for reading and see you next week!


########### Request Example ################# # URL https://app.divecentrehq.com/api/v1/products #Request Body { user_token: <USER_TOKEN>, store_api_key: <STORE_API_KEY>, page: 2, filter: "archived" } ########### Response Example ################ { products: [ { id: 15870, accounting_code: "", archived: false, barcode: "NTANKRENT", commission_rate_money: null, description: "RENTAL GEAR PER DAY", low_inventory_reminder: 5, markup: 0.0, name: "NITROX 80CU ALUMINUM (EAN 34 OR LESS FO2)", number_in_stock: 930, offer_price: null, retail_price: 17.0, sent_at: null, sku_code: "NTANKRENT", supplier_code: "", supply_price: 1.0, image: "/assets/missing/store_product/original.gif", brand: { id: 495, name: "GDC" }, category: { id: 1333, name: "RENTAL" }, supplier: { id: 655, name: "GDC" }, commission_rate: { id: 426, amount: 0.0 }, tax_rate: { id: 607, amount: 7.0 } }, { id: 22519, accounting_code: "", archived: false, barcode: "DGSERV", commission_rate_money: null, description: "Dive Guide Services 1 Day", low_inventory_reminder: 0, markup: 0.0, name: "Dive Guide Services 1 Day", number_in_stock: 5, offer_price: null, retail_price: 100.0, sent_at: "2014-06-14T23:00:26+01:00", sku_code: "DGSERV", supplier_code: "", supply_price: "0.0", brand: { id: 937, name: "GDC" }, category: { id: 1743, name: "Dive Services" }, supplier: { id: 655, name: "GDC" }, commission_rate: { id: 417, amount: 8.0 }, tax_rate: { id: 607, amount: 7.0 } } ] }
| Param Name | Description |
|---|---|
|
user_token required |
User Token Value: Must be String |
|
store_api_key required |
Store API Key Value: Must be String |
|
filter optional |
Return archived or unarchived products related from this param. If param is not exist then method will return unarchived products Value: Must be one of: archived, unarchived. |
|
page optional |
Number of page for products list. Each page has 50 products. By default method return page number 1 Value: Must be Integer |


Service Delivery Dashboard is only available from February 2019 onwards
{% comment %}
start-month will be the month number in the min-year from which reports are available
max-month will be the month number in the max-year till which reports are available
{% endcomment %}


Births in America Lowest in 35 Years
Last year the number of births in America was the lowest in 35 years.
Fewer and fewer babies are coming into this world.
Especially in America.
Also 13 countries and 25 states in America have the child illness associated
With Covid-19.
These children ard dying ‘right and left’.
The people of Anerica are dying.
The world is also dying.
The people of Earth are alss dying.
Thei is the ’Time of the End’.
Thi is the ‘Time of Judgment’.
They have sent Covid-19 to bring this about.
It attacks the whole body.
If you don’t dye at first, it will come againand again until you die.
Even the one you call ‘God’ cannot help.
There is no place to run and no place to hide.
I have come from 15 million years in the furure
To see why this ‘Death’ took place.
One thing I do know is there is ‘Evil’ everywhere,
In all the relms associated with this one except Heavan’,
There is no one to help.
Not ‘God’, not Jesus, not the Angels nor the Aliens.
So everyone dies.
I have dreamt twice of the final days.
There were only 5 people on Earth.
They were gathering in one place.
The saddness was overwhelming
I became very afraid.
I was overcme with fear.
The fear was ‘mindblowing’.


| GEOS SDK TechDocs
The following documents contain information specific to the
Nokia 9000/9000i Communicator device.
- Tutorial
- Shows the step-by-step creation of a simple Nokia 9000i Communicator application.
- Nokia 9000/9000i Communicator Fact Sheet
- One-stop reference guide to the the Nokia 9000/9000i Communicator.
- Versions
- Detecting the software version running on the user's device at run time,
and some of the differences between versions.
- Communicator UI
- Nokia 9000i Communicator-specific object classes useful for creating application UI.
- Distributing Software
- How to package up your finished Nokia 9000i Commuincator application
to make it easy for users to load it onto their devices.
- Memory Levels
- Routines which detect and warn of low memory levels.
- SMS
- Using the Short Message Service.
- Modem Connections
- Using the phone as a virtual modem.
- Contacts
- Accessing the user's contact information--phone numbers, addresses,
names, and so on.
- Calendar API
- How to insert appointments and events to the user's calendar.
| GEOS SDK TechDocs


Screen is a web portal to the terminal! More importantly, it is a collaboration tool that allows users to share a terminal session online.
Screen is not a complete project. There are issues with piping information back and forth to a terminal, especially in interactive CLI’s. But this was still a great learning experience.
You can view the full code on GitHub. The below preview is the room.pm module. It creates room objects for users to collaborate in. It also creates a shell for each room and executes the terminal commands.
package room;
use strict; use warnings;
use feature 'switch';
use helpers;
use set;
use shell;
######################################### GLOBALS ########################################
our %nametoroom = ();
#################################### HELPER FUNCTIONS ####################################
our @namepool = ();
open( my $FH, '<', 'public/lexis.txt' ) or die 'Could not open the lexis!!!'; push @namepool => trim(lc $_) while( <$FH> ); # rooms are stored as lowercase, so the keys must be lc too!
close( $FH ) or die 'Could not CLOSE the lexis!';
sub rand_name{
my $randindex = int( $#namepool * rand() );
return $namepool[$randindex]
}
sub name_to_room{ # creates a new room if necessary
my ($name) = @_;
return $nametoroom{$name} //= room->new(name=>$name) or die 'Bad room name string!' # adds the room to our hash if necessary
}
sub htmlify{ # this takes any amount of terminal stdout and converts it to html.
my ( $str, $prompt ) = @_;
# put a span around the commands...
# $prompt = quotemeta $prompt;
# $str =~ s|^(.*)\n|$1\n|; # the very first command is NOT preceded by a prompt.
# $str =~ s|\n?$prompt(.*)\n|\n$1\n|g; # this also makes sure that prompts always start on new lines.
# $str =~ s|\n?$prompt$|\n|; # delete final prompt. Also, all endings have newlines regardless of what bash outputted.
# $str =~ s|\n$|\n\n|g; # for an outputless command, let's display an empty line to show that.
$str =~ s|\n|
|g;
return $str
}
######################################## NEW ROOM ########################################
sub new{
my $packagename = shift;
my %options = @_; # includes the NAME of the room.
my $room = bless {
name => $options{name},
shell => undef,
controllers => set->new,
output => '',
}
=> $packagename;
$room->shell('sh');
return $room
}
########################################## ROOM ##########################################
sub name{
my $room = shift;
return $$room{name}
}
sub shell{
my $room = shift;
my ($shellname) = @_;
if( defined $shellname ){
$room->shell->close if defined $room->shell;
$$room{shell} = shell->new( $shellname, $room );
my $divider = "\n###############################################################\n";
$room->append($divider."Welcome to a new $shellname shell!\n\n");
}
return $$room{shell}
}
sub controllers{ # this is a SET of controllers
my $room = shift;
return $$room{controllers}
}
sub add_controller{
my $room = shift;
my ($controller) = @_;
$room->controllers->add_element($controller)
}
sub remove_controller{ say 'removing a controller...';
my $room = shift;
my ($controller) = @_;
$room->controllers->remove_element($controller);
# check if the room is empty. if so, close the room.
if( $room->controllers->is_empty ){ say 'closing the room...'; $room->close }
}
sub output{ # gets all the output of a room for a new self joining in
my $room = shift;
return $$room{output}
}
sub append_to_output{
my $room = shift;
my ($string) = @_;
$$room{output} .= $string;
}
sub append{
my $room = shift;
my ($string) = @_;
$room->append_to_output($string);
# my $html = htmlify( $string, $room->shell->prompt );
my $html = htmlify( $string );
$room->jblast( command=>'append', output=>$html );
#say "output is now $$room{output}";
}
sub jblast{ # blast is replaced with jblast, which includes the json in it
my $room = shift;
#say 'jblasting to '.scalar $room->controllers->array.' controllers.';
my %ball = @_; say 'ball is '."@_";
foreach( $room->controllers->array ){ #say 'i have a controller '."$_";
$_->jsend(%ball)
}
#say 'done WITH CONTROLLERS';
}
use overload
'""' => \&stringify;
sub stringify{
my $room = shift;
my $toprint;
{
local $" = ',';
$toprint .= 'Roomname is '.$room->name."\n";
my @controllers = $room->controllers->array; $toprint .= "Controllers are: @controllers\n";
}
return $toprint
}
sub command{ # executes a shell command and relays the output to all controllers.
my $room = shift;
my ($command) = @_; # incoming command does not have a \n at the end.
say "command is $command"; #say "Bin is $Bin";
if( $command =~ /^(shell) +([^ ]*)/i ){ # capture special room commands: shells
my $keyword = $1;
my $argument = lc trim $2;
given($keyword){
when('shell'){ # the argument has already been verified in $self->command
$room->shell($argument);
$room->jblast( command=>'set', id=>'shellname', html=>$argument, color=>"#f12772" );
}
}
}
else{
# my $outappend = $room->shell->command($command);
my $outappend = "$command
" . $room->shell->command($command);
$room->append($outappend);
}
}
sub close{
my $room = shift;
$room->shell->close;
# tell each controller in the room to leave the room (reset roomname attribute, remove self from room->controllers, update GUI
foreach my $self ( $room->controllers->array ){ $self->leave_room }
delete $nametoroom{ $room->name }; # delete the room from the nametoroom hash
}
1