Introspection

From Rosetta Code

Jump to: navigation, search
Task
Introspection
You are encouraged to solve this task according to the task description, using any language you may know.

This task asks to

  • verify the version/revision of your currently running (compiler/interpreter/byte-compiler/runtime environment/whatever your language uses) and exit if it is too old.
  • check whether the variable "bloop" exists and whether the math-function "abs()" is available and if yes compute abs(bloop).

Extra credit:

  • Report the number of integer variables in global scope, and their sum.


Contents

[edit] Ada

Ada doesn't allow you to ask about compiler versions, but you can query specific parameters of the target, such as the range of the standard integer type, or the precision of the standard floating point type:

with Ada.Integer_Text_IO, Ada.Text_IO;
procedure Introspection is
use Ada.Integer_Text_IO, Ada.Text_IO;
begin
Put ("Integer range: ");
Put (Integer'First);
Put (" .. ");
Put (Integer'Last);
New_Line;
 
Put ("Float digits: ");
Put (Float'Digits);
New_Line;
end Introspection;

[edit] Aikido

The version of the Aikido interpreter is in the global scope variable version. AIkido doesn't have abs but it does have fabs. Getting the variables in main involves getting their names and then evaluating them as an expression in order to retrieve their type.

 
import math
 
if (version < 144) {
throw "Version of aikido is too old"
}
 
var bloop = -1.4
 
// Math package doesn't have 'abs'. We'll use 'fabs' instead.
if ("fabs" in Math) {
if ("bloop" in main) {
println ("fabs(bloop) is " + eval ("Math.fabs(bloop)"))
}
}
 
var x = 104
var y = 598
var z = "hello"
var a = 1234
 
function count_ints {
// there are builtin integer variables that we don't want to count. There are
// 3 of them
var intcount = 0
// map of builtin variables we want to ignore
var ignore = {"version":true, "int":true, "integer":true}
var sum = 0
 
// the 'split' function can be used to split a block into a vector of the names
// of the variables within it
foreach v split (main, 0) {
var varname = v
try {
var value = eval (varname)
if (typeof(value) == "integer") {
if (varname in ignore) {
continue
}
intcount++
sum += value
}
} catch (e) {
// ignore exception
}
}
println ("There are " + intcount + " integer variables in the global scope")
println ("Their sum is " + sum)
}
 
count_ints()
 
 
 

Here is the result:

fabs(bloop) is 1.4
There are 3 integer variables in the global scope
Their sum is 1936


[edit] ALGOL 68

ALGOL 68 doesn't allow you to ask about compiler versions, but you can use constants specifying parameters of the target, such as the range of the standard integer type, or the precision of the standard floating point type.

Also: The constant(s) int lengths (real lengths) is the number (+1) of long precision types of int (reals) available at run time.

Translation of: Ada

Works with: ALGOL 68 version Standard - no extensions to language used Works with: ALGOL 68G version Any - tested with release mk15-0.8b.fc9.i386 Works with: ELLA ALGOL 68 version Any (with appropriate job cards) - tested with release 1.8.8d.fc9.i386

BEGIN
print (("Integer range: ", -max int, " .. ", max int, new line));
print (("Integer digits: ", int width, new line));
print (("Float range: ", -max real, " .. ", max real, new line));
print (("Float digits: ", real width, new line))
END

Output:

Integer range: -2147483647 .. +2147483647
Integer digits:         +10
Float range: -1.79769313486235e+308 .. +1.79769313486235e+308
Float digits:         +15

[edit] AutoHotkey

if (A_AhkVersion < "1.0.48.03")
{
MsgBox % "you are using" . A_AhkVersion . "`nplease upgrade to" . "1.0.48.03"
ExitApp
}
bloop = -3
if bloop
if IsFunc("abs")
MsgBox % abs(bloop)
return

[edit] C

Determining the make and version of the compiler, C standard, and environment features is one of the primary uses of the C preprocessor. This has allowed C to become the lingua franca of the open source movement.

Works with: C version 94 and later

#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
#pragma error("C compiler must adhere to at least C99 for the following code.")
#else
/* rest of file */
#endif

However, there is no facility in C for checking whether individual variables and functions have been declared. In open source, the GNU autotools are often used for this purpose, doing this kind of check in a shell script and defining symbols such as __HAVE_ABS__ which can be checked by the preprocessor.

[edit] Clojure

Partial answer...

 
; check Java version
(let [version (Double/parseDouble (re-find #"\d*\.\d*" (System/getProperty "java.version")))]
(if (>= version 1.5)
(println "Version ok")
(throw (Error. "Bad version"))))
 
; check Clojure version
(let [version (Double/parseDouble (re-find #"\d*\.\d*" (clojure-version)))]
(if (>= version 1.0)
(println "Version ok")
(throw (Error. "Bad version"))))
 


[edit] Common Lisp

(let* ((ver (lisp-implementation-version))
(major (parse-integer ver :start 0 :end (position #\. ver))))
#+lispworks (assert (>= 5 major) () "Requires Lispworks version 5 or above")
#+clisp (assert (>= 2 major) () "Requires CLISP 2.n")
)
(defvar bloop -4)
(if (and (fboundp 'abs)
(boundp 'bloop))
(format t "~d~%" (abs bloop)))

The list-all-packages and do-symbols forms enable a lisp program to examine all symbols and these can be tested to identify integer variables.

(let ((sum 0)
(ints '()))
(loop for pkg in (list-all-packages)
do (do-symbols (s pkg)
(when (and (boundp s)
(integerp (symbol-value s)))
(push s ints)
(incf sum (symbol-value s)))))
(format t "there are ~d integer variables adding up to ~d~%"
(length ints) sum))

[edit] D

The DMD compiler has macros defined for the version, more easily accessible through std.compiler:

import std.compiler;
static if (version_major < 2 || version_minor > 7) {
// this prevents further compilation
static assert (false, "I can't cope with this compiler version");
}

To check if something compiles or not:

version(D_Version2) {
 
static if( __traits(compiles,abs(bloop)) ) {
 
typeof(abs(bloop)) computeAbsBloop() {
return abs(bloop);
}
 
}
} else static assert(0, "Requires D version 2");

Note that this checks that bloop is of a type which abs() accepts. It is generic code; if the type of abs() changes, so will the return type of the function. The test can also be written so that it will work on D version 1:

static if ( is(typeof(abs(bloop))) ) {
typeof(abs(bloop)) computeAbsBloop() {
return abs(bloop);
}
}

[edit] Factor

Check for build number and execute a quotation if it's too old. (There are no such things as versions for Factor yet.)

: if-older ( n true false -- )
[ build > ] 2dip if ; inline
 
: when-older ( n true -- )
[ ] if-older ; inline
: unless-older ( n false -- )
[ [ ] ] dip if-older ; inline
 
900 [ "Your version of Factor is too old." print 1 exit ] when-older

It is possible to test if a function or a variable exists (search), but that shouldn't be used outside of parsing.

"bloop" search [
get [
"abs" search [ execute( n -- n' ) ] when*
] [ 0 ] if*
] [ 0 ] if*

On the other hand, it is possible to search the global namespace for integer variables:

USING: assocs formatting kernel math namespaces ;
 
0 0
global [
nip dup integer? [ + [ 1 + ] dip ] [ drop ] if
] assoc-each
"There are %d integer variables, the sum is %d\n" printf

[edit] E

Version:

def version := interp.getProps()["e.version"]

(There is no built-in version comparison, and the author of this example assumes that implementing a version comparison algorithm isn't the point of this task.)

Existence:

escape fail {
def &x := meta.getState().fetch("&bloop", fn { fail("no bloop") })
if (!x.__respondsTo("abs", 0)) { fail("no abs") }
x.abs()
}

This will return either bloop.abs(), "no bloop", or "no abs".

Sum of integers:

{
var sum := 0
for &x in interp.getTopScope() { sum += try { x :int } catch _ { 0 } }
sum
}

try rather than an ordinary type check is used because in general a slot might be broken; this way we skip over all read failures as well as non-integers. The block around the code ensures that the sum variable itself will not be involved in the computation.

[edit] Forth

Standard Forth doesn't necessarily provide for version numbers, but you can query information about the environment at interpretation time:

s" MAX-U" environment? [IF]
0xffffffff <> [IF] .( Requires 32 bits! ) bye [THEN]
[THEN]
 
[defined] bloop [if]
[defined] abs [if]
bloop @ abs
[then] [then]

[edit] Haskell

import Data.Version
import Control.Monad
import System.Info
 
minGHCVersion = Version [6, 8] []
 
main = when (compilerName == "ghc" && compilerVersion < minGHCVersion) $
fail "Compiler too old."

No means exists of checking whether a variable exists at runtime. The set of variables that exist in any given scope is fixed at compile-time.

[edit] Io

if(System version < 20080000, exit)
 
if(hasSlot("bloop") and bloop hasSlot("abs"), bloop abs)

Io can also inspect the source code of methods written in Io:

getSlot("arbitraryMethod") code

[edit] J

Exit if we're running an old version of J (earlier than version 6, which is current as of this writing), giving version number as the exit status:

6 (2!:55@:]^:>) 0 ". 1 { 9!:14''

Compute abs(bloop) if abs is a function and bloop is data:

".(#~3 0*./ .=4!:0@;:)'abs bloop'

Extra credit: report the number of integer variables in global scope, and their sum:

((],&(+/);@#~)((=<.)@[^:](''-:$)*.0=0{.@#,)&>)".&.>4!:1]0

This last expression is longer than the others, because it has a couple of extra guard checks; in J, the programmer doesn't need to care if the data is a single number or an array, or what hardware representation is used for numbers (32-bit int, IEEE float, etc).

So this expression takes pains to emulate solutions in other languages (i.e. only reports globals that are single numbers, and whose value = floor(value), so that even if the number is represented as a float in the machine, you still get the right answer).

[edit] Java

You can't see if a variable or function is available in Java (it will be a compile time error if you try to use them when you they aren't available), but you can check the version number using the System class:

public class VersCheck {
public static void main(String[] args) {
String vers = System.getProperty("java.version");
vers = vers.substring(0,vers.indexOf('.')) + "." + //some String fiddling to get the version number into a usable form
vers.substring(vers.indexOf('.')+1,vers.lastIndexOf('.'));
if(Double.parseDouble(vers) >= 1.5){
System.out.println("YAY!");
}else{
System.err.println("Must use Java >=1.5");
}
}
}

[edit] Logo

Works with: UCB Logo

show logoversion   ; 5.6
if logoversion < 6.0 [print [too old!]]
 
if and [name? "a] [number? :a] [
print ifelse procedure? "abs [abs :a] [ifelse :a < 0 [minus :a] [:a]]
]

[edit] Lua

if _VERSION:sub(5) + 0 < 5.1 then print"too old" end --_VERSION is "Lua <version>".
 
if bloop and math.abs then print(math.abs(bloop)) end

[edit] MAXScript

fn computeAbsBloop bloop =
(
versionNumber = maxVersion()
 
if versionNumber[1] < 9000 then
(
print "Max version 9 required"
return false
)
 
if bloop == undefined then
(
print "Bloop is undefined"
return false
)
 
try
(
abs bloop
)
catch
(
print "No function abs"
false
)
)
 
computeAbsBloop -17

[edit] OCaml

# Sys.ocaml_version;;
- : string = "3.10.2"
# Scanf.sscanf (Sys.ocaml_version) "%d.%d.%d"
(fun major minor micro -> major, minor, micro) ;;
- : int * int * int = (3, 10, 2)

Checking if an identifier (a value or a function) is bound doesn't make any sens in OCaml, which is strongly staticaly typed.

For optionnal values we would rather use a structure to contain them, for example an association lists for a small amount of items, or an hash table for a huge amount of data. Both can contain expressions or functions.

[edit] Oz

We cannot check whether a variable is in scope (static property). We can check whether a module exports a certain value. However, for system modules the compiler will refuse to compile if we try to use a non-existing value.

declare
Version = {Property.get 'oz.version'}
%% Version is an atom like '1.4.0'. So we can not compare it directly.
%% Extract the version components:
[Major Minor Release] = {Map {String.tokens {Atom.toString Version} &.} String.toInt}
in
if Major >= 1 andthen Minor >= 4 then
%% check whether module Number exports a value 'abs':
if {HasFeature Number abs} then
{Show {Number.abs ~42}}
end
else
{System.showInfo "Your Mozart version is too old."}
end

[edit] Perl

Works with: Perl version 5.x

require v5.6.1;    # run time version check
require 5.6.1; # ditto
require 5.006_001; # ditto; preferred for backwards compatibility
#$bloop = -123; # uncomment this line to see the difference
if (defined($::{'bloop'})) {print abs(${'bloop'})} else {print "bloop isn't defined"};

The trick in this example is to use bloop variable by reference ${'bloop'} (otherwise it will be created unconditionally by the compiler). Perl store nametables inside hashes: '::' - for main package and 'xxx::' for package 'xxx'. In Perl, you cannot check for the existence of built-in functions, of which abs() is one. However in practice that's not a problem because most functions live in classes, and those are easily inspectable at runtime.

use UNIVERSAL qw(can);
use Math::Cephes qw();
print Math::Cephes->fabs($bloop) if can 'Math::Cephes', 'fabs';

An example that solves the task:

use 5.010;
our $bloop = -12;
if (defined $::bloop) {
if (eval { abs(1) }) {
say 'abs($bloop) is ' . abs($::bloop);
}
else {
say 'abs() is not available';
}
}
else {
say '$bloop is not defined';
}

Note that this program will exit with a message "Perl v5.10.0 required" if run under perl version lower than 5.10 and it actually uses a feature introduced in that version (say). The program checks whether the variable is actually defined and not if it just exists. In Perl a variable can exist and have an undefined value and checking for existence is problematic because many read-only operations may create an empty slot in the global namespace as a side effect. It doesn't make sense to calculate absolute values of existent but undefined variables so it doesn't matter in this task. It can be tested by commenting out the our $bloop line. The existence of abs() function is tested using eval that returns false if the abs(1) cannot be invoked which can be tested by changing the name of the function in the eval test.

Extra task:

use 5.010;
package test;
use Regexp::Common;
use List::Util qw(sum);
 
our $a = 7;
our $b = 1;
our $c = 2;
our $d = -5;
our $e = 'text';
our $f = 0.25;
 
my @ints = grep { /^$RE{num}{int}$/ } map { $$_ // '' } values %::test::;
my $num = @ints;
my $sum = sum @ints;
say "$num integers, sum = $sum";

It prints:

4 integers, sum = 5

This example uses the test namespace instead of the default because there already are some integer numbers in the main namespace like the PID, etc. The program to sum those numbers would be:

use 5.010;
use Regexp::Common;
use List::Util qw(sum);
my @ints = grep { /^$RE{num}{int}$/ } map { $$_ // '' } values %::;
my $num = @ints;
my $sum = sum @ints;
say "$num integers, sum = $sum";
4 integers, sum = 74717

[edit] PHP

<?php
 
if (version_compare(PHP_VERSION, '5.3.0', '<' ))
{
echo("You are using PHP Version " . PHP_VERSION . ". Please upgrade to Version 5.3.0\n");
exit();
}
$bloop = -3;
if (isset($bloop) && function_exists('abs'))
{
echo(abs($bloop));
}
echo(count($GLOBALS) . " variables in global scope.\n");
echo(array_sum($GLOBALS) . " is the total of variables in global scope.\n");
 
?>

[edit] PicoLisp

(unless (>= (version T) (3 0 1))       # Check version (only in the 64-bit version)
(bye) )
 
# (setq bloop -7) # Uncomment this to get the output '7'
 
(and
(num? bloop) # When 'bloop' is bound to a number
(getd 'abs) # and 'abs' defined as a function
(println (abs bloop)) ) # then print the absolute value

[edit] PL/I

 
S = SYSVERSION();
if substr(S, 6, 6) < '050000' then
do; put skip list ('Version of compiler is too old'); stop; end;
 

[edit] Pop11

Variable pop_internal_version contains Poplog version in numeric form (as an integer) -- this one is most convenient for version checks. For printing one can use pop_version (which is a string containing more information).

;;; Exit if version below 15.00
if pop_internal_version < 150000 then
sysexit()
endif;

Pop11 variables are named by words. Pop11 word is a unique version of string stored in dictionary. So we need first convert strings to words and then query about words. Pop11 variables can store any value including functions and in fact when one accesses a function like abs by name one merely access a variable abs which happen to hold predefined function abs. To follow spirit of the task as closely as possible we check if abs indeed holds functional value.

;;; We do main task in a procedure
define check_and_call(x, y);
lvars wx=consword(x), wy=consword(y);
if identprops(wx) = 0 and isprocedure(valof(wx))
and identprops(wy) = 0 then
return(valof(wx)(valof(wy)));
else
return("failed");
endif;
enddefine;
 
;;; Prints failed because bloop is undefined
check_and_call('abs' , 'bloop') =>
;;; Define bloop
vars bloop = -5;
;;; Now prints 5
check_and_call('abs' , 'bloop') =>

Note that here bloop is defined as "permanent" variable, Pop11 also have lexical variables which are not available for introspection.

[edit] PowerShell

# version is found in $PSVersionTable
if ($PSVersionTable['PSVersion'] -lt '2.0') {
exit
}
 
if ((Test-Path Variable:bloop) -and ([Math]::Abs)) {
[Math]::Abs($bloop)
}
 
# find integer variables and their sum
Get-Variable -Scope global `
| Where-Object { $_.Value -is [int] } `
| Measure-Object -Sum Value `
| Select-Object Count,Sum

[edit] PureBasic

CompilerIf #PB_Compiler_Version<441
CompilerError "You failed the version check!"
CompilerEndIf
 
CompilerIf Defined(bloop,#PB_Variable)
CompilerIf Defined(Abs(),#PB_Function)
Abs(bloop)
CompilerEndIf
CompilerEndIf

[edit] Python

# Checking for system version
import sys
major, minor, bugfix = sys.version_info[:3]
if major < 2:
sys.exit('Python 2 is required')
 
 
def defined(name): # LBYL (Look Before You Leap)
return name in globals() or name in locals() or name in vars(__builtins__)
 
def defined2(name): # EAFP (Easier to Ask Forgiveness than Permission)
try:
eval(name)
return True
except NameError:
return False
 
if defined('bloop') and defined('abs') and callable(abs):
print abs(bloop)
 
if defined2('bloop') and defined2('abs') and callable(abs):
print abs(bloop)

You can combine both tests, (But loose sight of which variable in missing/not callable by wrapping the whole function call in a try-except statement:

try:
print abs(bloop)
except (NameError, TypeError):
print "Something's missing"

Here is one way to print the sum of all the global integer variables:

def sum_of_global_int_vars():
variables = vars(__builtins__).copy()
variables.update(globals())
print sum(v for v in variables.itervalues() if type(v) == int)
 
sum_of_global_int_vars()

[edit] R

Works with: R version 2.10.1

 
if(getRversion() < "2.10.1")
{
warning("Your version of R is older than 2.10.1")
q() # exit R, with the option to cancel
}

R.Version() and R.version give further information about the version that is running.

We now perform three checks: we want to know if bloop is in the user workspace (global environment), if abs exists somewhere, and if abs is a function.

bloop <- -3.4
if(exists("bloop", envir=globalenv()) && exists("abs") && is.function(abs))
{
abs(bloop)
}

Finally, we count how many integers are in the user workspace, and find their total. Note that a number followed by the letter L is considered to be an integer. See Integer_literals#R for more information.

#Declare some integers
qqq <- 45L
www <- -3L
#Retrieve the name of all the variables in the user workspace
varnames <- ls()
#Retrieve the actual variables as a list
allvars <- mget(varnames, envir=globalenv())
#See which ones are integers
isint <- sapply(allvars, is.integer)
#Count them
sum(isint)
#Retrieve the variables that were integers
theints <- mget(varnames[isint], envir=globalenv())
#Add them up
sum(unlist(theints))

[edit] Raven

VERSION 0 prefer 20071104 <
if 'version >= 20071104 required' print bye
 
'bloop' GLOBAL keys in && 'abs' CORE keys in
if bloop abs print

[edit] Ruby

exit if RUBY_VERSION < '1.8.6'
puts bloop.abs if defined?(bloop) and bloop.respond_to?(:abs)

Extra credit:

def variable_counter(b)
int_vars = []
sum = 0
check_var = lambda do |name, value|
if value.is_a?(Integer)
int_vars << name
sum += value
end
end
 
Kernel.global_variables.each {|varname| check_var.call(varname, eval(varname))}
eval('local_variables', b).each {|varname| check_var.call(varname, eval(varname, b))}
 
puts "these #{int_vars.length} variables in the global scope are integers:"
puts int_vars.inspect
puts "their sum is: #{sum}"
end
 
an_int = 5
a_string = 'foo'
a_float = 3.14
 
variable_counter(binding)

Output:

these 4 variables in the global scope are integers:
["$$", "$.", "$SAFE", "an_int"]
their sum is: 3239

The meaning of these variables can be found many places, including here.

[edit] Slate

No version string included inside the system presently.

Platform run: StartupArguments first ; ' --version'.
(lobby hasSlotNamed: #bloop) /\ [(#abs findOn: {lobby bloop}) isNotNil] ifTrue: [inform: bloop abs printString].
lobby slotValues inject: 0 into: [| :sum :value | (value is: Integer) ifTrue: [sum + value] ifFalse: [sum]].

[edit] Smalltalk

Works with: GNU Smalltalk

| s v t sum hm |
"uncomment the following to see what happens if bloop exists"
"Smalltalk at: #bloop put: -10."
s := Smalltalk version.
(s =~ '(\d+)\.(\d+)\.(\d+)')
ifMatched: [:match |
v := (( (match at: 1) asInteger ) * 100) +
(( (match at: 2) asInteger ) * 10) +
( (match at: 3) asInteger )
].
( v < 300 )
ifTrue: [
Transcript show: 'I need version 3.0.0 or later' ; cr ]
ifFalse: [
Transcript show: 'Ok! I can run!' ; cr .
"does bloop exists as global var?"
t := Smalltalk at: #bloop
ifAbsent: [
Transcript show: 'bloop var does not exist as global!' ; cr .
^nil
].
(t respondsTo: #abs)
ifTrue:
[ Transcript show: 'Absolute value of bloop: ' ;
show: (t abs) printString ; cr ].
] .
 
"how many 'numbers' in global scope, and compute their sums"
hm := 0.
sum := 0.
(Smalltalk keys) do: [ :els |
( (Smalltalk at: els) isKindOf: Number )
ifTrue: [ hm := hm + 1.
sum := sum + (Smalltalk at: els).
"Transcript show: (els asString) ; cr" ]
] .
Transcript show: 'Num of global numeric vars: '; show: (hm printString); cr ;
show: 'Sum of global numeric vars: '; show: (sum printString) ; cr.

[edit] Tcl

package require Tcl 8.4 ; # throws an error if older
if {[info exists bloop] && [llength [info functions abs]]} {
puts [expr abs($bloop)]
}

Extra credit:

namespace eval ::extra_credit {
variable sum_global_int 0
variable n_global_int 0
foreach var [info vars ::*] {
if {[array exists $var]} continue
if {[string is int -strict [set $var]]} {
puts "$var = [set $var]"
incr sum_global_int [set $var]
incr n_global_int
}
}
puts "number of global ints = $n_global_int"
puts "their sum = $sum_global_int"
}

[edit] TI-89 BASIC

()
Prgm
Local l, i, vers
getConfg() → l
For i,1,dim(l),2
If l[i] = "OS Version" or l[i] = "Version" Then
l[i + 1] → vers
Disp "Version: " & vers
If expr(right(vers, 4)) < 2005 Then © Lousy parsing strategy
Disp vers & " is too old"
Stop
EndIf
EndIf
EndFor
 
If isVar(bloop) Then © Dynamic name check can be done with isVar(#aString)
© Builtin functions cannot be tested for.
Disp abs(bloop)
Else
Disp "No bloop"
EndIf
 
© There is no way to get a list of global variables.
EndPrgm

[edit] Toka

Works with: Toka version 1.1+

Starting with Release 1.1, Toka allows for checking the version number:

VERSION 101 > [ bye ] ifFalse

Release 1.0 can be detected by doing:

` VERSION FALSE = [ bye ] ifTrue

Basic introspection is possible via `

` bloop FALSE <> ` abs FALSE <> and [ ` bloop invoke @ ` abs invoke ] ifTrue

[edit] Ursala

When the user defined function maybe_abs(x) is evaluated, a run time check is performed for the availability of the system library's absolute value function (fabs), and if found, it is used. If not, the function tries to invoke a replacement function named 'abs' from the imported floating point function library, flo. (The search for a replacement is performed at the time maybe_abs is compiled, and is possible because any imported library is presented as a list of (identifier:value) pairs.) If no imported absolute value function is available either, maybe_abs returns a copy of the argument x unchanged.

The #preprocess directive allows arbitrary user defined transformations to be applied to the abstract syntax trees created by the compiler (assuming a knowledge of the compiler internals). This example of a preprocessor aborts compilation if the run time system version differs from 0.10.2. Otherwise, a search is performed for any declared symbol named 'bloop' whose evaluation has been resolved, and its value is replaced with the absolute value as given by maybe_abs.

On platforms where at least one of the absolute value functions is available, the -1. shown in the source text will have been changed to 1 by the time it's displayed.

#import std
#import flo
#import lag
 
maybe_abs = math.|fabs (%QI flo)-:~&! 'abs'
 
#preprocess version==-[0.10.2]-?\<'wrong version'>!% *^0 ||~& -&
-&~&vitB,~&d.lexeme=='=',~&vhd.lexeme=='bloop',~&vthd.lexeme=='(evaluated)'&-,
&vthd.semantics:= !+ !+ maybe_abs+ ~&vthd.semantics.&iNHiNH&-
 
#cast %e
 
bloop = -1.

output:

1.000000e+00
Personal tools
Support