Development Tools

_images/unicon.png

Index Unicon

Unicon tools

The main Unicon command set is made up of:

  • unicon
  • icont
  • iconx
  • iconc

Todo

complete the list of core tools

After a source build with Unicon 13, the bin/ directory includes:

prompt$ ls -gGF --time-style=+
total 36692
-rwxrwxr-x 1    15843  counter_deref*
-rwxrwxr-x 1    15830  counter_line*
-rwxrwxr-x 1    15843  counter_pcall*
-rwxrwxr-x 1    15856  counter_syntax*
-rwxrwxr-x 1    28903  deadvar*
-rw-rw-r-- 1    40160  dlrgint.o
-rwxrwxr-x 1    30172  failedloop*
-rwxrwxr-x 1    24285  failedsubscript*
-rwxrwxr-x 1   332720  iconc*
-rwxrwxr-x 1   158512  icont*
-rwxrwxr-x 1  1188272  iconx*
-rwxrwxr-x 1    48671  ie*
-rwxrwxr-x 1   674993  ivib*
-rwxrwxr-x 1   187737  ivibmigrate*
-rwxrwxr-x 1    85592  libcfunc.so*
-rw-rw-r-- 1   398614  libgdbm.a
-rw-rw-r-- 1   323136  libtp.a
-rw-rw-r-- 1   642152  libXpm.a
-rwxrwxr-x 1    33129  looptime*
-rwxrwxr-x 1    44800  memory*
-rwxrwxr-x 1   143071  memory_alloc*
-rwxrwxr-x 1    24112  patchstr*
-rwxrwxr-x 1    39278  procprofile*
-rwxrwxr-x 1    24636  proctime*
-rw-rw-r-- 1 29658270  rt.a
-rw-rw-r-- 1   158925  rt.db
-rw-rw-r-- 1   333377  rt.h
-rwxrwxr-x 1   234384  rtt*
-rwxrwxr-x 1    24170  structaliases*
-rwxrwxr-x 1    48780  structusage*
-rwxrwxr-x 1    26217  typechange*
-rwxrwxr-x 1   223696  udb*
-rwxrwxr-x 1   838269  ui*
-rwxrwxr-x 1    39298  umake*
-rwxrwxr-x 1   205355  unicon*
-rwxrwxr-x 1   743000  unidep*
-rwxrwxr-x 1   325162  unidoc*
-rwxrwxr-x 1    74080  uprof*
-rwxrwxr-x 1    39435  varprofile*

The unicon command

unicon is the main command line tool for programming with Unicon.

Options include:

prompt$ unicon --help
Usage: unicon [-cBCstuEGyZMhK] [-Dsym=val] [-f[adelns]...] [-o ofile]
   [-nofs] [-help] [-version] [-features] [-v i] file... [-x args]
options may be one of:
   -B          : bundle VM (iconx) into executable
   -c          : compile only, do not link
   -C          : generate (optimized) C code executable
   -Dsym[=val] : define preprocessor symbol
   -e efile    : redirect icont's standard error output to efile
   -E          : preprocess only, do not compile
   -features   : report Unicon features supported in this build
   -fs         : prevent removal of unreferenced declarations
   -G          : generate graphics (wiconx) executable
   -M          : report error message to the authorities
   -o ofile    : generate executable named ofile
   -O          : optimize (under construction)
   -s          : work silently
   -t          : turn on tracing
   -u          : warn of undeclared variables
   -v i        : set diagnostic verbosity level to i
   -version    : report Unicon version
   -x args     : execute immediately
   -y          : parse (syntax check) only, do not compile
   -Z          : compress icode
   -K           : keep tmpfiles
   -h          : display this information

unicon is a wrapper around other tools, mainly the icont command. Many of the command lines options are similar, but unicon does a better job of explaining the options in the brief help.

Compiled unicon

C compiled Unicon, to be more specific, seeing as Unicon already compiles.

unicon -C translates Unicon to C intermediates and then compiles the C code (usually via native assembler source) to native executable for the system in use. Some Unicon features are not available when using unicon -C, such as native concurrency at this point in time.

Quiet unicon

Yeah, this is was a little tricky.

Update: as of revision [r4497] this entire sequence has been simplified. Just use unicon -s.

Left in for anyone running pre [r4497] Unicon.

prompt$ unicon version.icn
Parsing version.icn: .
/home/btiffin/uni13/unicon/bin/icont -c   -O version.icn /tmp/uni89441204
Translating:
version.icn:
  main
No errors
/home/btiffin/uni13/unicon/bin/icont  version.u
Linking:

Let’s try -quiet (it’s undocumented in -help)

prompt$ unicon -quiet version.icn
Translating:
version.icn:
  main
No errors
Linking:

Umm, not quite, how about -s, work silently.

prompt$ unicon -quiet -s version.icn

So close. Now to set verbosity to 0.

prompt$ unicon -quiet -s -v0 version.icn

Ahh, that’d be the ticket. Quiet, silent, not verbose.

-quiet -s -v0
prompt$ unicon -quiet -s -v0 version.icn -x
Unicon Version 13.0.  August 10, 2017

Update as above: Just use unicon -s.

The flip side is pretty easy; maximum verbosity.

prompt$ unicon -v3 version.icn -x
Parsing version.icn: .
/home/btiffin/uni13/unicon/bin/icont -c  -v3  -O version.icn /tmp/uni10135057
Translating:
version.icn:
  main
No errors
/home/btiffin/uni13/unicon/bin/icont -v3  version.u -x
Linking:
  bootstrap      344
  header         216
  procedures     152
  records          8
  fields           0
  globals         64
  statics          0
  linenums        80
  strings         23
  total          887
Executing:
Unicon Version 13.0.  August 10, 2017

The icont command

icont is the translator portion of the Unicon tool chain.

Options include:

prompt$ icont
usage: icont [-cBstuEG] [-f s] [-l logfile] [-o ofile] [-v i] file ... [-x args]

icont is a relatively sophisticated compiler, most error messages are quite comprehensive, detailing what it wrong with the source code.

#
# Compile time error message example
#
procedure main()
    a ::= "1" + []
end
prompt$ icont compiletime-error.icn
Translating:
compiletime-error.icn:
compiletime-error.icn:12: # "a": syntax error (91;366)
File compiletime-error.icn; Line 14 # traverse: undefined node type

::= is not valid assignment syntax.

Like most high level compilers, sometimes the error messages are, less helpful:

Todo

ADD SAMPLE

And sometimes, you need to wait until execution time, and triggering an error at run-time.

#
# Runtime error message example
#
procedure main()
    a := "1" + []
end

Sample run, with error:

prompt$ unicon runtime-error.icn -x
Parsing runtime-error.icn: .
/home/btiffin/uni13/unicon/bin/icont -c   -O runtime-error.icn /tmp/uni77531835
Translating:
runtime-error.icn:
  main
No errors
/home/btiffin/uni13/unicon/bin/icont  runtime-error.u -x
Linking:
Executing:

Run-time error 102
File runtime-error.icn; Line 12
numeric expected
offending value: list_1 = []
Traceback:
   main()
   {1 + list_1 = []} from line 12 in runtime-error.icn

Integer can’t be added to a List datatype, in this case, an integer coerced from a string.

See Testing Unicon for some details on testing Unicon programs.


The iconx command

iconx is the Executor portion of the Unicon tool chain.

iconx takes the filename to execute.

The Icon Virtual machine, and iconx, report any runtime errors, in a relatively comprehensive manner.

#
# Runtime error message example
#
procedure main()
    a := "1" + []
end
prompt$ unicon -c runtime-error.icn
Parsing runtime-error.icn: .
/home/btiffin/uni13/unicon/bin/icont -c   -O runtime-error.icn /tmp/uni89441204
Translating:
runtime-error.icn:
  main
No errors

iconx processes icode files, which are binary executable forms created during the link phase from ucode files.

prompt$ iconx runtime-error

Run-time error 102
File runtime-error.icn; Line 12
numeric expected
offending value: list_1 = []
Traceback:
   main()
   {1 + list_1 = []} from line 12 in runtime-error.icn

A segue into .u files, ucode, and the Icon Virtual Machine.

.u files are Icon cross platform machine instructions, as human readable source (this feature helped with the design and debugging of the virtual machine).

For example, the above buggy runtime-error.icn was translated to runtime-error.u, and is a human readable form of the Icon Virtual Machine language.

version	U12.1.00
uid	runtime-error.u1-1480545330-0
impl	local
global	1
	0,000005,main,0

proc main
	local	0,000000,a
	con	0,010000,1,061
	declend
	filen	runtime-error.icn
	line	11
	colm	11
	synt	any
	mark	L1
	pnull
	var	0
	pnull
	str	0
	pnull
	line	12
	colm	16
	synt	any
	llist	0
	line	12
	colm	14
	synt	any
	plus
	line	12
	colm	7
	synt	any
	asgn
	unmark
lab L1
	pnull
	line	13
	colm	1
	synt	any
	pfail
	end

If you look at the first few lines of a unicon compiled program, it is actually a script that starts iconx with the ucode embedded in it.

prompt$ unicon runtime-error.icn
Parsing runtime-error.icn: .
/home/btiffin/uni13/unicon/bin/icont -c   -O runtime-error.icn /tmp/uni18241759
Translating:
runtime-error.icn:
  main
No errors
/home/btiffin/uni13/unicon/bin/icont  runtime-error.u
Linking:
prompt$ cat -v runtime-error | par
#!/bin/sh IXBIN=/home/btiffin/uni13/unicon/bin/iconx IXLCL=`echo $0 |
sed 's=[^/]*$=iconx='`

[ -n "$ICONX" ] && exec "$ICONX" [ -x "$IXLCL" ] && exec  "$0" ${1+"$@"}
"$IXLCL" [ -x "$IXBIN" ] && exec "$IXBIN" exec iconx      "$0" ${1+"$@"}

[executable Icon binary follows]

^L
^@[^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@M-8^@^@^@^@^@^@^@M-@^@^@^@^@^@^@^@M-@^@
^^@^@^@^@^@^@M-@^@^@^@^@^@^@^@M-P^@^@^@^@^@^@^@M-`^@^@^@^@^@^@^@@^A^@^@^
^@^@^@^@M-`^@^@^@^@^@^@^@M-p^@^@^@^@^@^@^@I12.U.30/32/64^@^@p
^M-5^A^@^@^@^@^@^@^@^@^@^@^@^@@dM-4^A^@^@^@^@M-0^MM-5^A^@^@^@^@M-^@`M-4^
^A^@^@^@^@@`M-4^A^@^@^@^@M-^LM-^IM-hM-^M'^?^@^@@dM-4^A^@^@^@^@^@^@^@^@^@
^^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@p M-5^A^@^@^@^@p
^M-5^A^@^@^@^@^@^@^@^@^@^@^@^@^F^@^@^@^@^@^@^@X^@^@^@^@^@^@^@X^@^@^@^@^@
^^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^D^
^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^E^@^@^@^@^@^@^@b^@^@^@C^@
^^@^@D^@^@^@^@^@^@^@E^@^@^@S^@^@^@^@^@^@^@^@^@^@^@E^@^@^@M^@^@^@^A^@^@^@
^^@^@^@^@^G^@^@^@^@^@^@^@E^@^@^@A^@^@^@^@^@^@^@^@^@^@^@^^^@^@^@^A^@^@^@N
^^@^@^@E^@^@^@D^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^F^@^@^@^@^@^@M-0^@^@^@^@^@
^^@^@^@^D^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@X^@^@^@^@^@^@^@
^^@^@^@^@^@^@^@X^@^@^@^@^@^@^@^K^@`^A^@^@^@^@M-^T^@^@^@^@^@^@^@^L^@^@^B^
^@^@^@^@M-
^^@^@^@^@^@^@^@^L^@M-@^A^@^@^@^@M-$^@^@^@^@^@^@^@^L^@M-`^@^@^@^@^@M-0^@^
^@^@^@^@^@^@^M^@ ^@^@^@^@^@main^@a^@1^@runtime-error.icn^@

Coding conventions and style

Unicon has a long history, and Ralph Griswold tried to keep a consistent look and feel to both the compiler internal C/rtt sources and the high level Icon programs submitted to the IPL. That effort was not 100% successful, and the many hands that have touched on the C code each brought a slightly different style preference. One of the most startling format issue may be the mixing of tab characters and spaces for code indentation. The convention guide (https://www.cs.arizona.edu/icon/docs/ipd072.htm) requests spaces, but there are tabs in the sources and over time, various text editors have made the code look a little sloppy in terms of nested indentations. Keep to the request, and use spaces, as it avoids this long term churn issue with source code and text editor treatment of tabs.

IPL entries seem to have fared better over the years in terms of consistent look. That is likely due to the more public nature and numbers of interested readers, when compared to the internal source files.

In summary:

  • Indentation: Three spaces per level, with no tabs for indentation.
  • Line length: Not to exceed 80 characters with tabs expanded.
  • Inter-line spacing: At most one empty line as needed for visual clarity. Formfeed (^L) between function declarations (except where there are many short, similar functions). Generally one empty line prior to boxed comments.
  • Function declarations: storage/type class on line with function name. No indentation on argument declarations. Function body, including braces and local declarations indented three spaces. Braces enclosing functions on lines by themselves.
  • Braces: Beginning brace at end of line for construction involved (except for function declarations as noted above). Ending brace on separate line indented three spaces beyond position of opening construction.
  • if statements: statement below conditional expression, indented three spaces. If else is present, on separate line aligned with corresponding if.
  • Binary operators: one space on either side.
  • Argument lists: one space after each comma.
  • Return statements: no parentheses around argument of return.
  • Casts: no space between right parenthesis surrounding cast and the expression to which it applies.
  • typedefs: generally all lowercase (a deliberate departure from usual C conventions; typedefs in the Icon source code are viewed as an extension of the C language).
  • Comments: Boxed-style per numerous examples. Second and subsequent lines indented one character. “On-line” comments tabbed out as is most readable. No “cute” or illiterate comments. No personal identifications (they cease to be useful with time and produce cumulative clutter).
  • Conditional compilation: One empty line before and after #ifdef/endif groups. Identifying C-style comment five tabs out on #else and #endif directives. (I think by 5 tabs out, Ralph meant column 40).
  • Manifest (defined) constants and macros: For the most part, names should be in mixed upper- and lowercase (a deliberate departure from usual C conventions). Specifically, an uppercase letter identifies a name that has been defined as opposed to a C variable. Mixed case is used for readability.

This convention guide carries over to Unicon sources and IPL entries, where appropriate. In particular, IPL entries all start with a consistent comment block, formatted to allow the indexing tool to properly do its job. See the ipl-skeleton.icn listed below for this formatting standard.

Note

The examples in this docset all break rule one. I prefer 4 space indents. The bracing rule is also broken, preferring to not indent the closing brace, but to keep it at the same indentation as the starting construct.

Apologies, but that is the way it is.

With that said, reasonable effort is expended to maintain an internal consistency.

The convention guide calls for code formatting ala:

while line := read(f) do {
   result := stuff(line)
   morestuff(result)
   }
continuing()

This document uses a style of the form:

while line := read(f) do {
    result := stuff(line)
    morestuff(result)
}
continuing()

Blame age and long ingrained personal preference for the breach of project preferred convention.

It behooves any Unicon programmer to get used to many forms and coding styles, as for the most part, due to many hands in the pot, you may encounter different formatting in any one particular source file. A key issue is to strive for consistency and to attempt some level of source formatting discipline.


Supporting tools

Unicon works very well with most of the common software development tools available for various operating systems. This docset focuses on GNU/Linux, but other systems also offer a wide range of useful development aids.

Unicon also ships with a fair number of support tools, custom built for Unicon development.

XKCD Fixing Problems
"'What was the original problem you were trying to fix?' 'Well, I noticed one
of the tools I was using had an inefficiency that was wasting my time'"

XKCD http://xkcd.com/1739/ by Randall Munroe CC BY-NC 2.5


make

make is not a Unicon specific program, but works very well with Unicon development. make is also used when building Unicon from source.

See https://www.gnu.org/software/make/manual/make.html for details of the ubiquitous GNU implementation of make.

make normally uses a non visible Tab character (ASCII 9) to prefix action lines. GNU make includes an extension to specify a different prefix character. The example below, and other examples throughout this documentation use a more visible > action statement prefix. This is not supported in all versions of make, but it makes copy and paste from web pages a little safer, as it removes any chance of a Tab character being mistaken for spaces.

Some sample recipes:

# Unicon programming starter Makefile sample
.RECIPEPREFIX = >

# quick help, first target is default target, "make" or "make help"
.PHONY: help
help:
> @echo "Unicon example Makefile"
> @echo
> @echo "make help\t\tfor this help"
> @echo "make program\t\tto build program.icn"
> @echo "make run\t\tto run executable from program.icn"
> @echo
> @echo "make name\t\tto build and run any given named .icn file"
> @echo "make -B name\t\twill force the run, even if already up to date"
> @echo "make name.u\t\tto build a link file for any given named .icn file"

# make Unicon program, $< is the first prereq
program: program.icn
> unicon $<

run: program
> ./$<

# generic rules
# build and run any given .icn file by typing "make name"
%: %.icn
> unicon -s $^ -x

# create a linkable Unicon file by typing "make name.u"
%.u: %.icn
> unicon -c $^

examples/Makefile

make program will compile program.icn if the source is more recent than the target executable, make run will run the program (and ensure it is up to date before execution, if sources have changed). $< is an automatic make variable, set to match the first prerequisite. For the program: target, the first (and only) prerequisite is program.icn. For the sample run: target, the prerequisite is program, and $< is substituted in to execute ./program.

make is a fairly powerful tool. There are quite a few features that may not be apparent at first glance. See the GNU make manual referenced above for more details.

A special note on the trick %: %.icn and %.u: %.icn targets. Those are make patterns that match any named Unicon source file, name.icn, and compiles and/or runs the program. It is a convenience feature for non-project related make. It allows any Unicon file to be compiled and run by simply typing make name. If the source has already been compiled (date of executable is later than the date time of last edit), just use ./name, or use make -B name to force a new compile and run. To compile a source file for use with link, the same trick allows make name.u, to match the name.icn file, and then run unicon -c on the given name.

Again, those are convenience features, normally a Makefile is specific to a project and the targets will include specific instructions for clean up, packaging, installation, etcetera, and will list all prerequisite source files, not singletons as used with the trick filename matching rules.


ui

The Unicon IDE. ui ships with Unicon, under the uni/ide subdirectory, and is built along with unicon and the other command line tools, ready to use with any Unicon installation that supports the 2D graphics facilities. A graphical front end for Unicon development, detailed in Technical Report UTR12a, http://unicon.org/utr/utr12.html

The Ui source code provides lots of examples for extending and customizing a graphical user interface generated using IVIB, the interface building tool.

Ui supports project management, file management, a contextual help based source code editor, a class browser, along with Compile, Run and Debug layers.

I’ll be honest, I develop on the command line, with Vim and associated tools. If you prefer Integrated Development Environments, be sure to fire up ui.

Might have to pester Clinton about opening up the font selection list; the four X11 fonts that ship with Unicon are not as beautiful as some that are now available for GNU/Linux.


UDB

The Unicon debugger. A very comprehensive Unicon support tool.

Modelled on GNU gdb, udb allows breakpoints, Unicon source view, structure display, and many other high and low level debugging features using a command prompt interface.

UDB, by Ziad Al-Sharif, is documented in Unicon Technical Report 10.

http://unicon.org/utr/utr10.html

See Debugging for more details.


IVIB

A visual, graphical user interface building tool. Drag and drop user interface elements to generate Unicon code.


The Icon Virtual Machine

ucode

ucode is source form virtual machine instructions, transportable between all platforms. The translator generates ucode as an intermediate form ready for the link stage. ucode was named before Unicon, as part of the Icon project.

Starting small, smaller than Hello in this case.

#
# onestatement.icn, a single statement
#
# tectonics:
#     unicon -c onestatement.icn
#
procedure onestatement()
    u := 1
end

examples/onestatement.icn

Producing ucode from this source gives a close to minimum set of VM instructions required for the Unicon VM.

Processed via unicon -c

prompt$ unicon -c onestatement.icn ; sed -i 's/\x0C//' onestatement.u
Parsing onestatement.icn: .
/home/btiffin/uni13/unicon/bin/icont -c   -O onestatement.icn /tmp/uni15859885
Translating:
onestatement.icn:
  onestatement
No errors

Generates a link ready ucode file, onestatement.u. [1]

version	U12.1.00
uid	onestatement.u1-1505285444-0
impl	local
global	1
	0,000005,onestatement,0

proc onestatement
	local	0,000000,u
	con	0,002000,1,1
	declend
	filen	onestatement.icn
	line	14
	colm	11
	synt	any
	mark	L1
	pnull
	var	0
	int	0
	line	15
	colm	7
	synt	any
	asgn
	unmark
lab L1
	pnull
	line	16
	colm	2
	synt	any
	pfail
	end

examples/onestatement.u

This assigns the value 1 to the local variable, u.

The ucode file also includes some identification, some procedure paperwork, the statement trace info, and the statement bounding markers, along with the actual low level instructions to assign a 1 to u.

The Unicon virtual machine is stack based. An operational stack is used very much like a Forth data stack. Pushing and popping values (which can be encoded or literal) while performing virtual machine level operations that functionally match the high level Unicon source instructions.

The action opcodes here being

pnull
var 0
int 0
asgn

Push a null descriptor (a place holder for the expression result). Push the id of variable 0 from the declarations (the u). Push an integer with id 0 from the constant declarations (a 1 in this case). Then assign; asgn pops the value and destination while performing the assignment operation and replaces the initial null descriptor with the result (which in more complex programs would be chained to other parts of an expression).

ucode is the human friendly version of icode, the actual byte-code used by the virtual machine. During initial development of Icon, starting back in 1978ish, it was deemed important to have a human readable version of the VM instruction sequencing. This helped (and still helps) verify and debug the Icon source code translator. A nice touch, not really necessary for the virtual machine itself, but of great importance to the people implementing the engine and the translator. And a bonus to developers that can peruse the machine instructions.

As is, this ucode requires one more step before being executable code. The rt runtime translator at the heart of the Unicon VM always starts with main. It gives the engine a starting point, a place to call home that ensures everything is properly initialized. The translation from ucode to icode happens during the linking phase of the Unicon tool chain. All link references are included, and ucode files merged and resolved down to icode.

Many Unicon programs are singletons, no link statements to worry about, but every final step icode generation requires a main. In this case, the single statement procedure is compiled separately and included in the file listed below via the link reserved word.

#
# mainstatement.icn, link to a single statement procedure
#
# tectonics:
#     unicon -c onestatement.icn
#     unicon mainstatement.icn
#
link onestatement
procedure main()
    mainstatement()
end

examples/mainstatement.icn

That piece of code will link to onestatement.u and produce an executable VM image, mainstatement. mainstatement sits ready to be invoked by the operating system to run the program. A program that invokes main (implicitly), which invokes onestatement, which sets u to 1, then runs down, giving control back to the operating system.

For now, we are more interested in looking at the ucode, so unicon -c comes into play again.

prompt$ unicon -c mainstatement.icn ; sed -i 's/\x0C//' mainstatement.u
Parsing mainstatement.icn: ..
/home/btiffin/uni13/unicon/bin/icont -c   -O mainstatement.icn /tmp/uni15859885
Translating:
mainstatement.icn:
  main
No errors
version	U12.1.00
uid	mainstatement.u1-1505285444-0
impl	local
link	onestatement.u
global	1
	0,000005,main,0

proc main
	local	0,000000,mainstatement
	declend
	filen	mainstatement.icn
	line	16
	colm	12
	synt	any
	mark	L1
	var	0
	line	17
	colm	18
	synt	any
	invoke	0
	unmark
lab L1
	pnull
	line	18
	colm	1
	synt	any
	pfail
	end

examples/mainstatement.u

We don’t really have an executable yet, the Unicon tool chain stopped after producing the mainstatement ucode and did not combine the sources with the runtime engine, nor generate icode.

prompt$ unicon mainstatement.icn

Parsing mainstatement.icn: ..
/home/btiffin/unicon/bin/icont -c   -O mainstatement.icn /tmp/uni18898220
Translating:
mainstatement.icn:
  main
No errors
/home/btiffin/unicon/bin/icont  mainstatement.u
Linking:

Without -c, Unicon does the complete pass, including the VM link phase, and creates a new program, ready to run.

./mainstatement

That pass does nothing visible, but did all kinds of nifty things in the background.

Hello

Now making it a little more complicated is the Hello, world of ucode.

#
# hellostatement.icn, a single statement, proof of life
#
# tectonics:
#     unicon -c hellostatement.icn
#
procedure hellostatement()
    write("Hello, world")
end

examples/hellostatement.icn

Producing ucode from this source gives just enough VM instructions for Unicon to create a procedure that displays evidence that a proper installation of Unicon is functional.

Processed via unicon -c:

prompt$ unicon -c hellostatement.icn ; sed -i 's/\x0C//' hellostatement.u
Parsing hellostatement.icn: .
/home/btiffin/uni13/unicon/bin/icont -c   -O hellostatement.icn /tmp/uni17050822
Translating:
hellostatement.icn:
  hellostatement
No errors

Generates a link ready ucode file, hellostatement.u.

version	U12.1.00
uid	hellostatement.u1-1505285444-0
impl	local
global	1
	0,000005,hellostatement,0

proc hellostatement
	local	0,000000,write
	con	0,010000,12,110,145,154,154,157,054,040,167,157,162,154,144
	declend
	filen	hellostatement.icn
	line	14
	colm	11
	synt	any
	mark	L1
	var	0
	str	0
	line	15
	colm	10
	synt	any
	invoke	1
	unmark
lab L1
	pnull
	line	16
	colm	1
	synt	any
	pfail
	end

examples/hellostatement.u

Linking that with a main that calls the small procedure and we have a Unicon virtual machine program to tell the world that Unicon is functioning properly (and in this case, doubly so; the translator works and the linker works, along with the runtime engine).

#
# hellomain.icn, link to a write statement procedure
#
# tectonics:
#     unicon -c hellostatement.icn
#     unicon hellomain.icn
#
link hellostatement
procedure main()
    hellostatement()
end

examples/hellomain.icn

Drum roll...

prompt$ unicon -c hellostatement.icn ; unicon hellomain.icn -x ; sed -i 's/\x0C//' hellostatement.u
Parsing hellostatement.icn: .
/home/btiffin/uni13/unicon/bin/icont -c   -O hellostatement.icn /tmp/uni17050822
Translating:
hellostatement.icn:
  hellostatement
No errors
Parsing hellomain.icn: ..
/home/btiffin/uni13/unicon/bin/icont -c   -O hellomain.icn /tmp/uni15859885
Translating:
hellomain.icn:
  main
No errors
/home/btiffin/uni13/unicon/bin/icont  hellomain.u -x
Linking:
Executing:
Hello, world

From Unicon source files, through ucode, to linked icode and final creation of an executable file. Then automatically invoked (via -x) to demonstrate a functional Unicon installation by way of a friendly greeting.

[1]Unicon merged ucode into a single file. Icon, separates some of the paperwork from the instructions, giving .u1 and .u2 files. Having a single .u file makes things a little cleaner and more easily transportable.

icode

icode is binary form virtual machine instructions, and have an almost one to one correspondence with ucode source. Some differences will occur during linkage, the final phase of Unicon translation before executable. The executor, rt, is the runtime engine invoked by The iconx command that evaluates icode. When using GNU/Linux, Unicon create an executable shell script, that assists with search path settings, and then runs the included binary icode machine instructions.

The hellomain file (reformatted for document capture):

prompt$ ./show-icode hellomain
#!/bin/sh
IXBIN=/home/btiffin/uni13/unicon/bin/iconx                                    
IXLCL=`echo $0 | sed 's=[^/]*$=iconx='`

[ -n "$ICONX" ] && exec "$ICONX" "$0" ${1+"$@"}
[ -x "$IXLCL" ] && exec "$IXLCL" "$0" ${1+"$@"}
[ -x "$IXBIN" ] && exec "$IXBIN" "$0" ${1+"$@"}
exec iconx "$0" ${1+"$@"}

[executable Icon binary follows]
      
0000: 00 58 02 00 00 00 00 00 00 00 00 00 00 00 00 00  .X..............
0016: 00 28 01 00 00 00 00 00 00 30 01 00 00 00 00 00  .(.......0......
0032: 00 30 01 00 00 00 00 00 00 30 01 00 00 00 00 00  .0.......0......
0048: 00 60 01 00 00 00 00 00 00 90 01 00 00 00 00 00  .`..............
0064: 00 10 02 00 00 00 00 00 00 90 01 00 00 00 00 00  ................
0080: 00 b0 01 00 00 00 00 00 00 49 31 32 2e 55 2e 33  .........I12.U.3
0096: 30 2f 33 32 2f 36 34 00 00 e0 d1 89 00 00 00 00  0/32/64.........
0112: 00 00 00 00 00 00 00 00 00 50 14 89 00 00 00 00  .........P......
0128: 00 a0 d0 89 00 00 00 00 00 80 10 89 00 00 00 00  ................
0144: 00 40 10 89 00 00 00 00 00 8c 09 d7 49 e1 7f 00  .@..........I...
0160: 00 50 14 89 00 00 00 00 00 00 00 00 00 00 00 00  .P..............
0176: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0192: 00 e0 d1 89 00 00 00 00 00 e0 d1 89 00 00 00 00  ................
0208: 00 00 00 00 00 00 00 00 00 06 00 00 00 00 00 00  ................
0224: 00 48 00 00 00 00 00 00 00 48 00 00 00 00 00 00  .H.......H......
0240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0256: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0272: 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0288: 00 62 00 00 00 43 00 00 00 24 00 00 00 00 00 00  .b...C...$......
0304: 00 62 00 00 00 54 00 00 00 01 00 00 00 00 00 00  .b...T..........
0320: 00 62 00 00 00 3d 00 00 00 00 00 00 00 00 00 00  .b...=..........
0336: 00 4e 00 00 00 45 00 00 00 44 00 00 00 00 00 00  .N...E...D......
0352: 00 06 00 00 00 00 00 00 00 48 00 00 00 00 00 00  .........H......
0368: 00 d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0384: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0400: 00 00 00 00 00 00 00 00 00 0e 00 00 00 00 00 00  ................
0416: 00 05 00 00 00 00 00 00 00 62 00 00 00 43 00 00  .........b...C..
0432: 00 3c 00 00 00 00 00 00 00 62 00 00 00 54 00 00  .<.......b...T..
0448: 00 02 00 00 00 00 00 00 00 62 00 00 00 4d 00 00  .........b...M..
0464: 00 0c 00 00 00 00 00 00 00 28 00 00 00 00 00 00  .........(......
0480: 00 62 00 00 00 3d 00 00 00 01 00 00 00 00 00 00  .b...=..........
0496: 00 4e 00 00 00 45 00 00 00 44 00 00 00 00 00 00  .N...E...D......
0512: 00 00 00 00 00 00 00 00 00 06 00 00 00 00 00 00  ................
0528: b0 00 00 00 00 00 00 00 00 06 00 00 00 00 00 00  ................
0544: b0 88 00 00 00 00 00 00 00 06 00 00 00 00 00 00  ................
0560: b0 a7 ff ff ff ff ff ff ff 04 00 00 00 00 00 00  ................
0576: 00 00 00 00 00 00 00 00 00 0e 00 00 00 00 00 00  ................
0592: 00 05 00 00 00 00 00 00 00 05 00 00 00 00 00 00  ................
0608: 00 14 00 00 00 00 00 00 00 48 00 00 00 00 00 00  .........H......
0624: 00 1a 00 00 00 00 00 00 00 d0 00 00 00 00 00 00  ................
0640: 00 35 00 00 00 00 00 00 00 48 00 00 00 00 00 00  .5.......H......
0656: 00 10 00 80 01 00 00 00 00 68 00 00 00 00 00 00  .........h......
0672: 00 11 00 60 02 00 00 00 00 80 00 00 00 00 00 00  ...`............
0688: 00 12 00 20 00 00 00 00 00 d0 00 00 00 00 00 00  ... ............
0704: 00 0e 00 60 01 00 00 00 00 08 01 00 00 00 00 00  ...`............
0720: 00 0f 00 40 01 00 00 00 00 20 01 00 00 00 00 00  ...@..... ......
0736: 00 10 00 20 00 00 00 00 00 6d 61 69 6e 00 68 65  ... .....main.he
0752: 6c 6c 6f 73 74 61 74 65 6d 65 6e 74 00 77 72 69  llostatement.wri
0768: 74 65 00 68 65 6c 6c 6f 6d 61 69 6e 2e 69 63 6e  te.hellomain.icn
0784: 00 48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 00 68 65  .Hello, world.he
0800: 6c 6c 6f 73 74 61 74 65 6d 65 6e 74 2e 69 63 6e  llostatement.icn
0816: 00                                               .

icode support files

icode is based on single byte operation codes.

/*
 * Opcode definitions used in icode.
 */

/*
 * Operators. These must be in the same order as in odefs.h.  Not very nice,
 *  but it'll have to do until we think of another way to do this.  (It's
 *  always been thus.)
 */
#define Op_Asgn		  1
#define Op_Bang		  2
#define Op_Cat		  3
#define Op_Compl	  4
#define Op_Diff		  5
#define Op_Div		  6
#define Op_Eqv		  7
#define Op_Inter	  8
#define Op_Lconcat	  9
#define Op_Lexeq	 10
#define Op_Lexge	 11
#define Op_Lexgt	 12
#define Op_Lexle	 13
#define Op_Lexlt	 14
#define Op_Lexne	 15
#define Op_Minus	 16
#define Op_Mod		 17
#define Op_Mult		 18
#define Op_Neg		 19
#define Op_Neqv		 20
#define Op_Nonnull	 21
#define Op_Null		 22
#define Op_Number	 23
#define Op_Numeq	 24
#define Op_Numge	 25
#define Op_Numgt	 26
#define Op_Numle	 27
#define Op_Numlt	 28
#define Op_Numne	 29
#define Op_Plus		 30
#define Op_Power	 31
#define Op_Random	 32
#define Op_Rasgn	 33
#define Op_Rcv		 34
#define Op_RcvBk	 35
#define Op_Refresh	 36
#define Op_Rswap	 37
#define Op_Sect		 38
#define Op_Snd		 39
#define Op_SndBk	 40
#define Op_Size		 41
#define Op_Subsc	 42
#define Op_Swap		 43
#define Op_Tabmat	 44
#define Op_Toby		 45
#define Op_Unions	 46
#define Op_Value	 47
/*
 * Other instructions.
 */
#define Op_Bscan	 117
#define Op_Ccase	 118
#define Op_Chfail	 119
#define Op_Coact 	 120
#define Op_Cofail	 48
#define Op_Coret 	 49
#define Op_Create	 50
#define Op_Cset  	 51
#define Op_Dup   	 52
#define Op_Efail 	 53
#define Op_EInit 	 116
#define Op_Eret  	 54
#define Op_Escan 	 55
#define Op_Esusp 	 56
#define Op_Field 	 57
#define Op_Goto  	 58
#define Op_Init  	 59
#define Op_Int   	 60
#define Op_Invoke	 61
#define Op_Keywd 	 62
#define Op_Limit 	 63
#define Op_Line  	 64
#define Op_Llist 	 65
#define Op_Lsusp 	 66
#define Op_Mark  	 67
#define Op_Pfail 	 68
#define Op_Pnull 	 69
#define Op_Pop   	 70
#define Op_Pret  	 71
#define Op_Psusp 	 72
#define Op_Push1 	 73
#define Op_Pushn1 	 74
#define Op_Real   	 75
#define Op_Sdup   	 76
#define Op_Str    	 77
#define Op_Unmark 	 78
#define Op_Var    	 80
#define Op_Arg		 81
#define Op_Static	 82
#define Op_Local	 83
#define Op_Global	 84
#define Op_Mark0	 85
#define Op_Quit		 86
#define Op_Tally	 88
#define Op_Apply	 89


/*
 * "Absolute" address operations.  These codes are inserted in the
 * icode at run-time by the interpreter to overwrite operations
 * that initially compute a location relative to locations not known until
 * the icode file is loaded.
 */
#define Op_Acset	 90
#define Op_Areal	 91
#define Op_Astr		 92
#define Op_Aglobal	 93
#define Op_Astatic	 94
#define Op_Agoto	 95
#define Op_Amark	 96


#define Op_Noop		 98


#define Op_Colm		108		/* column number */

/*
 * Declarations and such -- used by the linker but not the run-time system.
 */

#define Op_Proc		101
#define Op_Declend	102
#define Op_End		103
#define Op_Link		104
#define Op_Version	105
#define Op_Con		106
#define Op_Filen	107

/*
 * Global symbol table declarations.
 */
#define Op_Record	105
#define Op_Impl		106
#define Op_Error	107
#define Op_Trace	108
#define Op_Lab   	109
#define Op_Invocable	110

/*
 * Extra instructions added for calling Icon from C (used by Posix functions)
 */
#ifdef PosixFns
#define Op_Copyd        111
#define Op_Trapret      112
#define Op_Trapfail     113
#endif					/* PosixFns */

#define Op_Synt         114             /* syntax code used by the linker */
#define Op_Uid          115             /* Universal Identifier for .u files */
/* Op_EInit is 116 for now. */

examples/opdefs.h

Which is manually paired with

/*
 * Operator definitions.
 *  
 * Fields are:
 *    name
 *    number of arguments
 *    string representation
 *    dereference arguments flag: -1 = don't, 0 = do
 */

OpDef(asgn,2,":=",-1)
OpDef(bang,1,"!",-1)
OpDef(cater,2,"||",0)
OpDef(compl,1,"~",0)
OpDef(diff,2,"--",0)
OpDef(divide,2,"/",0)
OpDef(eqv,2,"===",0)
OpDef(inter,2,"**",0)
OpDef(lconcat,2,"|||",0)
OpDef(lexeq,2,"==",0)
OpDef(lexge,2,">>=",0)
OpDef(lexgt,2,">>",0)
OpDef(lexle,2,"<<=",0)
OpDef(lexlt,2,"<<",0)
OpDef(lexne,2,"~==",0)
OpDef(minus,2,"-",0)
OpDef(mod,2,"%",0)
OpDef(mult,2,"*",0)
OpDef(neg,1,"-",0)
OpDef(neqv,2,"~===",0)
OpDef(nonnull,1,BackSlash,-1)
OpDef(null,1,"/",-1)
OpDef(number,1,"+",0)
OpDef(numeq,2,"=",0)
OpDef(numge,2,">=",0)
OpDef(numgt,2,">",0)
OpDef(numle,2,"<=",0)
OpDef(numlt,2,"<",0)
OpDef(numne,2,"~=",0)
OpDef(plus,2,"+",0)
OpDef(powr,2,"^",0)
OpDef(random,1,"?",-1)
OpDef(rasgn,2,"<-",-1)
OpDef(rcv,2,"@<",0)
OpDef(rcvbk,2,"@<<",0)
OpDef(refresh,1,"^",0)
OpDef(rswap,2,"<->",-1)
OpDef(sect,3,"[:]",-1)
OpDef(snd,2,"@>",0)
OpDef(sndbk,2,"@>>",0)
OpDef(size,1,"*",0)
OpDef(subsc,2,"[]",-1)
OpDef(swap,2,":=:",-1)
OpDef(tabmat,1,"=",0)
OpDef(toby,3,"...",0)
OpDef(union,2,"++",0)
OpDef(value,1,".",0)
/* OpDef(llist,1,"[...]",0) */

examples/odefs.h

There is also a set of Unicon application programmer support files, mainly used with Execution Monitoring and lower level debugging programs, available in the IPL.

  • ipl/incl/opdefs.icn, an include file with all opcode numbers
  • ipl/incl/invkdefs.icn, with definitions for visualizing the symbols
  • ipl/mprocs/opname.icn, string names for opcodes
  • and a few others peppered throughout the IPL.

In the end, Unicon creates an executable shell program that embeds the icode byte codes for use by the Unicon executor, iconx when producing a virtual machine program image.

The program used above to display the hellomain executable is a small Unicon program, show-icode.icn. It relies on the fact that the shell scripting is separated from the ucode by a form feed character. The shell script lines are displayed by line, and the rest as a hex dump.

#
# show-icode.icn, display the parts of a Unicon VM executable
#
link printf
procedure main(argv)
    f := open(argv[1], "r") | stop("Cannot open " || image(argv[1]))
    # the shell control preamble as lines
    while (line := read(f)) ~== "\^L" do write(line)

    # binary icode as hex dump
    # reads(f, -1) won't work here as the file is already reading
    s := ""
    while s ||:= reads(f)
    hexdump(s)

    close(f)
end

#
# display hex codes
#
procedure hexdump(s)
    local c, perline := 0, text := " ", scale := 0, counter := 0

    if *s = 0 then fail
    scale := **s
    scale <:= 4
    printf("%0" || scale || "d: ", counter)
    every c := !s do {
        if (perline +:= 1) > 16 then {
            write(text)
            text := " "
            perline := 1
            printf("%0" || scale || "d: ", counter)
        }
        #writes(map(_doprnt("%02x ", [ord(c)]), &lcase, &ucase))
        printf("%02x ", ord(c))
        text ||:= if 31 < ord(c) < 127 then c else "."
        counter +:= 1
    }
    if perline > 0 then {
        writes(repl(" ", (16 - perline) * 3))
        write(text)
    }
    else write()
end

examples/show-icode.icn

The Implementation of Icon and Unicon

As part of the Unicon release 13 pass, there has been updates occurring to The Implementation of Icon and Unicon book, probably the best place for details on the design of the Unicon virtual machine. Sources for ib.pdf ships with the Unicon source kit under doc/ib. Plus it’s an excellent book regarding how to go about building a programming language and the deep issues that designers face when embarking on the task.


Editors

Unicon source code is assumed to be ASCII. UFT-8 encoding will work, as long as the characters used stay as single byte code points, in the range 0 to 127.

This means word processor default formats are not suitable for Unicon source. If you like to use a word processor, make sure the source is saved as Text.

Literals and data can assume an 8bit range, 0 to 255, but anything beyond value 127 is at the whim of operating environment settings and default handling. Sometimes you will get block looking characters or upside down question marks, sometimes you will get an extended encoding value like line drawing characters. Those non ASCII features are not standard nor cross platform.

There are quite a few editors that support Icon in terms of highlighting, smart indenting and other productivity enhancers; less so with Unicon features added in. Listed below is an updated Vim syntax highlighter.


Vim

The world’s best text editor. A text processing tool.

Here is a Vim syntax file, customized for Unicon, building on the icon.vim that ships with Vim.

" Vim syntax file
" Language: Unicon
" Maintainer:   Brian Tiffin (btiffin@gnu.org)
" URL: https://sourceforge.net/projects/unicon
" Last Change:  2016 Oct 22

" quit when a syntax file was already loaded
if exists("b:current_syntax")
  finish
endif

" Read the Icon syntax to start with
runtime! syntax/icon.vim
unlet b:current_syntax

" Unicon function extensions
syn keyword uniconFunction Abort Any Arb Arbno array
syn keyword uniconFunction Break Breakx chmod chown
syn keyword uniconFunction chroot classname cofail Color
syn keyword uniconFunction condvar constructor 
syn keyword uniconFunction crypt ctime dbcolumns dbdriver
syn keyword uniconFunction dbkeys dblimits dbproduct dbtables display
syn keyword uniconFunction eventmask EvGet EvSend
syn keyword uniconFunction exec Fail fdup Fence fetch fieldnames
syn keyword uniconFunction filepair
syn keyword uniconFunction flock fork
syn keyword uniconFunction getegid geteuid getgid getgr
syn keyword uniconFunction gethost getpgrp getpid getppid getpw
syn keyword uniconFunction getrusage getserv gettimeofday
syn keyword uniconFunction getuid globalnames gtime
syn keyword uniconFunction ioctl istate
syn keyword uniconFunction keyword kill Len link load localnames lock
syn keyword uniconFunction max membernames methodnames
syn keyword uniconFunction methods min mkdir mutex name
syn keyword uniconFunction NotAny Nspan opencl oprec
syn keyword uniconFunction paranames parent pipe
syn keyword uniconFunction Pos proc
syn keyword uniconFunction readlink ready
syn keyword uniconFunction receive Rem rmdir Rpos Rtab
syn keyword uniconFunction select send setenv setgid setgrent
syn keyword uniconFunction sethostent setpgrp setpwent setservent setuid
syn keyword uniconFunction signal Span spawn sql stat staticnames
syn keyword uniconFunction structure Succeed symlink
syn keyword uniconFunction sys_errstr syswrite Tab
syn keyword uniconFunction trap truncate trylock
syn keyword uniconFunction umask unlock utime wait

" Unicon graphics, audio and VOIP
syn keyword uniconGraphics Active Alert
syn keyword uniconGraphics Attrib Bg
syn keyword uniconGraphics Clip Clone Color
syn keyword uniconGraphics ColorValue CopyArea
syn keyword uniconGraphics Couple 
syn keyword uniconGraphics DrawArc DrawCircle DrawCube DrawCurve
syn keyword uniconGraphics DrawCylinder DrawDisk DrawImage DrawLine
syn keyword uniconGraphics DrawPoint DrawPolygon DrawRectangle
syn keyword uniconGraphics DrawSegment DrawSphere DrawString DrawTorus
syn keyword uniconGraphics EraseArea Event
syn keyword uniconGraphics Eye Fg
syn keyword uniconGraphics FillArc FillCircle FillPolygon
syn keyword uniconGraphics FillRectangle Font FreeColor
syn keyword uniconGraphics GotoRC GotoXY
syn keyword uniconGraphics IdentityMatrix
syn keyword uniconGraphics Lower MatrixMode
syn keyword uniconGraphics MultMatrix
syn keyword uniconGraphics NewColor Normals
syn keyword uniconGraphics PaletteChars PaletteColor PaletteKey
syn keyword uniconGraphics Pattern Pending
syn keyword uniconGraphics Pixel PlayAudio PopMatrix
syn keyword uniconGraphics PushMatrix PushRotate PushScale PushTranslate
syn keyword uniconGraphics QueryPointer Raise ReadImage
syn keyword uniconGraphics Refresh Rotate
syn keyword uniconGraphics Scale
syn keyword uniconGraphics StopAudio
syn keyword uniconGraphics Texcoord Texture
syn keyword uniconGraphics TextWidth Translate
syn keyword uniconGraphics Uncouple
syn keyword uniconGraphics VAttrib
syn keyword uniconGraphics WAttrib WDefault WFlush
syn keyword uniconGraphics WindowContents
syn keyword uniconGraphics WriteImage WSection WSync

" Unicon system specific
syn keyword uniconSpecific FreeSpace GetSpace InPort Int86
syn keyword uniconSpecific OutPort Peek Poke Swi
syn keyword uniconSpecific WinAssociate WinButton WinColorDialog
syn keyword uniconSpecific WinEditRegion WinFontDialog WinMenuBar
syn keyword uniconSpecific WinOpenDialog WinPlayMedia WinSaveDialog
syn keyword uniconSpecific WinScrollBar WinSelectDialog

" Unicon and Icon Graphic Keywords
syn match uniconKeyword "&col"
syn match uniconKeyword "&column"
syn match uniconKeyword "&control"
syn match uniconKeyword "&errno"
syn match uniconKeyword "&eventcode"
syn match uniconKeyword "&eventsource"
syn match uniconKeyword "&eventvalue"
syn match uniconKeyword "&interval"
syn match uniconKeyword "&ldrag"
syn match uniconKeyword "&lpress"
syn match uniconKeyword "&lrelease"
syn match uniconKeyword "&mdrag"
syn match uniconKeyword "&meta"
syn match uniconKeyword "&mpress"
syn match uniconKeyword "&mrelease"
syn match uniconKeyword "&pick"
syn match uniconKeyword "&now"
syn match uniconKeyword "&rdrag"
syn match uniconKeyword "&resize"
syn match uniconKeyword "&row"
syn match uniconKeyword "&rpress"
syn match uniconKeyword "&rrelease"
syn match uniconKeyword "&shift"
syn match uniconKeyword "&window"
syn match uniconKeyword "&x"
syn match uniconKeyword "&y"

" New reserved words
syn keyword uniconReserved critical import initially invocable method
syn keyword uniconReserved package thread 

" Storage class reserved words
syn keyword uniconStorageClass  abstract class

" Define the highlighting colour groups
hi def link uniconStorageClass  StorageClass
hi def link uniconFunction      Statement
hi def link uniconGraphics      Special
hi def link uniconSpecific      SpecialComment
hi def link uniconReserved      Label
hi def link uniconKeyword       Operator

let b:current_syntax = "unicon"

programs/unicon.vim

Place that file in $HOME/.vim/syntax/unicon.vim. Then add

" Unicon - see ~/.vim/ftdetect/unicon.vim
autocmd BufRead,BufNewFile *.icn     set filetype=unicon

to your ~/.vimrc Vim startup file.

Or copy this short file type detection file

" Unicon file detection override Icon
" Modified: 2016-10-24/05:19-0400

autocmd BufRead,BufNewFile *.icn     set filetype=unicon

programs/unicon-ftdetect.vim

to $HOME/.vim/ftdetect/unicon.vim

Please note the filename is also unicon.vim but in the ~/.vim/ftdetect/ directory. It is renamed here as unicon-ftdetect.vim to avoid a name conflict within the documentation directory structure.

After saving the syntax file and changes to the file type auto detect system, whenever you open or edit a file with a .icn extension, it will be highlighted for Unicon syntax. As well as working with older Icon sources.

Once you add the syntax file, you can choose Unicon highlighting for any Vim buffer by typing the ex colon command, set filetype=unicon.

As hinted at in Documentation, you can also add automatic templates for new Unicon source files by adding the following to your ~./vimrc startup file.

autocmd BufNewFile  *.icn      0r ~/lang/unicon/header.icn
autocmd BufNewFile  *.opt      0r ~/lang/unicon/header-options.icn
    \ |0file|file <afile>:s?\.opt?\.icn?|filetype detect

Change the ~/lang/unicon/header part to a local site installation filename. It will pre-populate new .icn files with text from the template header.

The second Vim autocmd listed above allows for a more sophisticated skeleton for programs what will have command line option handling. Use with vim filename.opt. It loads a more extensive template (header-options), then renames the buffer to filename.icn. The .opt shortcut relies on having the unicon.vim file type detection code properly installed in ~/.vim/ftdetect.

At time of writing, my custom templates look like:

header.icn

##-
# Author: Brian Tiffin
# Dedicated to the public domain
#
# Date: October 2016
# Modified:
##+
#
# program.icn, description
#
# tectonics:
#
#
procedure main()

end

examples/header.icn

I use header.icn quite often, and keep the Date: line up to date with the current month.

header-options.icn

##-
# Author: Brian Tiffin
# Licensed under the GNU LGPL, version 3 or greater
#
# Date:
# Modified:
##+
# 
# program.icn, description
#
# tectonics:
#
$define VERSION 0.1

link options

procedure main(argv)
    opts := options(argv, "-h! -v! -source!", optError)
    if \opts["h"] then return showHelp()
    if \opts["v"] then return showVersion()
    if \opts["source"] then return showSource()

end

#
# show help, version and source info
#
procedure showVersion()
    write(&errout, &progname, " ", VERSION, " ", __DATE__)
end

procedure showHelp()
    showVersion()
    write(&errout, "Usage:")
    write(&errout, "\t-h\tshow this help")
    write(&errout, "\t-v\tshow version")
    write(&errout, "\t-source\tlist source code")
end

procedure showSource()
    local f
    f := open(&file, "r") | stop("Source file ", &file, " unavailable")
    every write(!f)
    close(f)
end

#
# options error
#
procedure optError(s)
    write(&errout, s)
    stop("Try ", &progname, " -h for more information")
end

examples/header-options.icn

Personalize to taste, and save a little typing when you start new Unicon files. Plus the added benefit of a consistent look to all of your programs (which are, by their very nature, the world’s best programs).

There is also the Icon Programming Library skeleton, developed by Ralph Griswold a long time ago, which is not a bad choice for consistent Unicon programming.

############################################################################
#
#	File:     
#
#	Subject:  Program
#
#	Author:   
#
#	Date:     
#
############################################################################
#
#  This file is in the public domain.
#
############################################################################
#
#
#
############################################################################
#
#  Requires:  
#
############################################################################
#
#  Links:
#
############################################################################

procedure main()

end

examples/ipl-skeleton.icn

A well supported, de-facto standard in the Icon world.


Emacs

The world’s other best text editor. An operating system that handles text.

Robert Parlett created a Unicon major more for Emacs:

http://www.zenadsl6357.zen.co.uk/unicon/

Evil

The Extensible Vi Layer for Emacs, Evil adds features of the world’s best text editor to the world’s other best text editor.

https://www.emacswiki.org/emacs/Evil

This is thee editor combination. Emacs (including OrgMode) with Vim key bindings and modal editing. Sweet. Evil is a very complete, robust and well done Vim emulator, augmenting the powers inherent in Emacs.


Index | Previous: Threading | Next: Documentation