#!perl
# $Id: 98_lambda.pm 1.20
##############################################################################
#
#     Copyright by Dieter Wegener
#     e-mail: dieter dot wegener dot md at gmail dot com
#
#     This file is part of fhem.
#
#     Fhem is free software: you can redistribute it and/or modify
#     it under the terms of the GNU General Public License as published by
#     the Free Software Foundation, either version 3 of the License, or
#     (at your option) any later version.
#
#     Fhem is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#     GNU General Public License for more details.
#
#     You should have received a copy of the GNU General Public License
#     along with fhem.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
use strict;
use DBI;
use Time::Local;
use Time::HiRes qw(gettimeofday);
no warnings 'qw';
use Scalar::Util;
package lambda;
	use constant hourSeconds => 60 * 60;
	use constant daySeconds => hourSeconds * 24;
	use constant pi => 4 * atan2 (1, 1);
package lambda::base;
	sub new {
		bless {}, shift;
	}
	sub isSymbol {}
	sub isConstant {}
	sub isLambda {}
	sub isThread {}
	sub isWait {}
	sub isWarning {}
	sub isUndefined {}
	sub isEmpty {}
	sub isPureEmpty {}
	sub isTerminate {}
	sub isQuit {}
	sub copy {shift}
	sub refresh {shift}
	sub check {shift}
	sub name {
		lambda::base::string (@_);
	}
	sub string {
		my $s = ref shift;
		$s =~ s/^lambda:://;
		$s;
	}
	sub compare {1}
	sub toXml {"<" . shift->string . " />"}
	sub toScriptXml {"<span>" . ref shift . "<span />"}
	sub getData {shift}
	sub erase {}
	sub includedDevices {()}
	sub id {
		sprintf (shift) =~ /HASH\((0x.{6})(.{6})\)/ ? 16777216 * hex ($1) + hex ("0x$2") : 0;
	}
package lambda::undefined;
	use vars ('@ISA');
	@ISA = qw (lambda::base);
	sub isUndefined {1}
	sub ancestor {
		my ($self, $class) = @_;
		! $class || $class->isUndefined ? $self : lambda::error->new (3, $self, $class);
	}
	sub string {"undefined"}
package lambda::quit;
	use vars ('@ISA');
	@ISA = qw (lambda::base);
	sub new {
		my $self = bless {}, shift;
		$self->{blockId} = shift->{id};
		$self;
	}
	sub isQuit {1}
package lambda::terminate;
	use vars ('@ISA');
	@ISA = qw (lambda::base);
	sub isTerminate {1}
package lambda::wait;
	use vars ('@ISA');
	@ISA = qw (lambda::base);
	sub isWait {1}
package lambda::warning;
	use vars ('@ISA');
	@ISA = qw (lambda::error);
	my %msgW = (
		0 => "Sonstige Warnung. &&1 &&2 &&3",
	);
	sub new {
		my $self = bless {}, shift;
		$self->{nr} = shift;
		$self->{parameter} = \@_;
		$self;
	}
	sub toXml {"<warning>". shift->string . "</warning>"}
	sub isError {}
	sub isWarning {1}
package lambda::empty;
	use vars ('@ISA');
	@ISA = qw (lambda::data);
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift;
		$self;
	}
	sub compare {
		my ($v1, $v2) = @_;
		my $c1 = $v1->{class};
		my $c2 = $v2->{class};
		return 0 if ! $c1 && ! $c2;
		return 1 if $c1 && $c2 && $c1->qName ne $c2->qName;
		return ! $v2->isEmpty;
	}
	sub isA {
		my $class = shift->{class};
		$class ? $class->isASubclass (shift) : undef;
	}
	sub isEmpty {1}
	sub isValue {shift->isPureEmpty}
	sub isPureEmpty {shift->{class} ? undef : 1}
	sub property {shift->{class}->property (@_)}
	sub string {
		my $class = shift->{class};
		$class ? "$class->{name}'empty" : "pureEmpty";
	}
package lambda;
	$lambda::error::msgE{"symbol_01"} = "leeres Symbol";
package lambda::symbol;
	use vars ('@ISA');
	@ISA = qw (lambda::base);
	my $temp = 0;
	sub new {
		my $self = bless {}, shift;
		my $name = $self->{value} = shift;
		if ($name) {
			$self->{value} =~ s/^('?)//;
			return lambda::error->new ("symbol_01") if ! $self->{value};
			$self->{quote} = 1 if $1 || shift;
		} else {
			$self->{value} = "#" . ++$temp . ";";
		}
		$self;
	}
	sub toWord {
		$lambda::master::word->new (shift->{value});
	}
	sub quote {
		shift->copy (1)
	}
	sub unQuote {
		lambda::symbol->new (shift->{value});
	}
	sub string {
		my $self = shift;
		my $value = $self->{value};
		$value =~ s/;$//;
		$self->{quote} ? "'" . $value : $value;
	}
	sub toScriptXml {
		my ($symbol, $class) = @_;
		my $s = $symbol->{value};
		$class ? "<span class=\"$class\">$s</span>" : $s;
	}
	sub isSymbol {
		my $t = shift->{value};
		$t =~ s/([\(\)\{\}\[\]\\\|\/\+\?\*\.\^\&\-])/\\$1/g;
		@_ ? (" " . join (" ", @_) . " ") =~ /\s$t\s/ ? 1 : undef : 1;
	}
package lambda::base;
	sub isError {}
package lambda::error;
	our $error;
	our %msgE = (
		 0 => "Sonstiger Fehler. &&1 &&2 &&3",
		 1 => "Funktion nicht definiert: &&1",
		 2 => "Symbol erwartet statt: &&1",
		 3 => "Kein gemeinsamer Vorfahre der Klassen &&1 und &&2.",
		 4 => "Ganze Zahl erwartet statt: &&1",
		 5 => "Symbol steht für eine Klasse und nicht für Variable: &&1",
		 6 => "Datei &&1 lässt sich nicht zum Lesen öffnen!",
		 7 => "Falscher Typ! &&1 ist nicht von Typ &&2.",
		 8 => "Ganze Zahl zwischen &&1 und &&2 statt &&3 erwartet.",
		 9 => "Klasse &&1 nicht definiert!",
		10 => "Liste erwartet statt: &&1",
		11 => "Objekt von Typ &&1 erwartet. Statt dessen: &&3 vom Typ &&2 &&4",
		12 => "Objekt hier nicht erlaubt: &&1",
		13 => "&&1 ist nicht der Name einer Klasse!",
		15 => "Syntaxfehler! Schließende runde Klammer oder Semikolon fehlt? &&1",
		16 => "Device &&1 existiert nicht!",
		17 => "Ganze Zahl größer &&1 statt &&2 erwartet.",
		18 => "Division durch Null!",
		19 => "Fehlerhafter Parameter '&&1' in: &&2",
		20 => "Variable '&&1' nicht initialisiert!",
		21 => "Symbol '&&1' bereits definiert.",
		22 => "Falsche Klammersetzung: &&1",
		23 => "Variable '&&1' bereits initialisiert!",
		24 => "Fehlerhafte Klassendefinition: &&1",
		25 => "Objektdefinition unvollständig! &&1",
		26 => "Variable '&&1' bereits initialisiert! Wert: &&2",
		27 => "Kein Zeitpunkt in der Zukunft: &&1",
		28 => "Eigenschaft &&1 existiert nicht im Objekt: &&2",
		29 => "Element mit Index &&1 existiert nicht!",
		30 => "Kein gültiger Wert für die Klasse 'word': &&1",
		31 => "Symbol ohne Wert: &&1",
		32 => "Die Klasse '&&1' kann nicht instanziiert werden.",
		33 => "Laufzeitüberschreitung. &&1",
		34 => "Device &&1 hat nicht den TYPE lambda!",
		35 => "Reading &&1 existiert nicht im Device &&2!",
		36 => "Syntaxfehler! Unerwartetes Scriptende.",
		37 => "Syntaxfehler! Fehlender Apostroph.",
		38 => "Syntaxfehler! Falsches Apostroph.",
		39 => "Syntaxfehler! Kein Blank nach String. &&1",
		40 => "Zahl ist nicht positiv. &&1",
		41 => "Statt Symbol &&1 Objekt von Typ &&2 erwartet.",
		42 => "&&1 hat den hier nicht zulässigen Wert empty. &&2",
		43 => "Messwerte unterschiedlicher Dimension: &&1 <> &&2",
		44 => "Operation nicht erlaubt bzw. nicht definiert. &&1",
		46 => "Ausdruck ohne Rückgabewert: &&1",
		47 => "Symbol erwartet nach '&&1' statt '&&2'.",
		48 => "Device von Typ lambda erwartet! &&1",
		49 => "regExpr unvollständig oder falsch! &&1",
		50 => "Klasse ist bereits definiert: &&1",
		51 => "Leerer Stack",
		52 => "Variable von Typ &&1 erwartet!",
		53 => "Klassenname statt &&1 erwartet!",
		54 => "Funktionsparameter erwartet statt: &&1",
		55 => "Variable erwartet! hier: &&1",
		56 => "Unbekannter Iterator! &&1",
		57 => "Erneute Festlegung der Eigenschaft &&3 auf &&1 nicht erlaubt. Alter Wert: &&2",
		58 => "Wert vom Typ timespan stellt keine Uhrzeit dar: &&1",
		59 => "Ungültiger Wert vom Typ timespan! &&1",
		60 => "Object von Typ &&1 erwartet. Statt dessen: Typ &&2",
		61 => "Variable aus anderen Thread erwartet. &&1",
		62 => "Konstante kann kein Parameter nach 'wait' sein. &&1",
		63 => "Wert erwartet statt &&1",
		64 => "Falscher Typ! &&1 ist von Typ &&2. Muss von einer Elternklasse von &&3 abstammen.",
		65 => "Klassendefinition von &&1 kann nicht um &&2 erweitert werden.",
		66 => "Klasse &&1 ist keine von &&2 abgeleitete Klasse.",
		67 => "Channel &&1 existiert nicht im Device &&2.",
		68 => "Initialisierungsblock hier nicht erlaubt. &&1",
		69 => "Funktionsparameter statt &&1 erwartet.",
		70 => "Datei &&1 lässt sich nicht zum Schreiben öffnen! &&2",
		71 => "Apostroph hier nicht zulässig: &&1",
		72 => "Ein Device kann nicht geklont werden. &&1",
		73 => "Klassen &&1 und &&2 sind nicht miteinander verwandt.",
		74 => "Mindestens ein Parameter ist 'empty': &&1",
		75 => "Die Werte &&1 und &&2 können nicht miteinander verglichen werden.",
		76 => "Vergleichsfuntion hat statt dem Rückgabewert 'boolean' einen Wert vom Typ &&1!",
		77 => "Unerlaubte leere Zeichenkette im Quellcode. &&1",
		78 => "&&1. Parameter in &&2 darf nicht 'empty' sein. Kommando: &&3",
		79 => "Funktional muss eine Rückgabewert haben.",
		80 => "Unerwartetes Blockende in &&1.",
		81 => "Falsches Datum: &&1 &&2",
	);
	use vars ('@ISA');
	@ISA = qw (lambda::terminate);
	sub new {
		my ($class, $nr, @p) = @_;
		my $self = $lambda::error ? $lambda::error : ($lambda::error = $lambda::error = bless {}, $class);
		$lambda::script =~ /^\s*(.{0,100})\s*(.*)\}$/ if $lambda::script;
		my $local = $2 ? "$1 ..." : $1;
		my $text = $msgE{$nr};
		my $i = 0;
		foreach (@p) {
			$i++;
			my $str = $_ ? (ref) ? "\'" . $_->string . "\'" : $_ : "";
			$text =~ s/&&$i/$str/g;
		}
		if ($text) {
			$text =~ s/&&\d+//g;
		} else {
			$text = "";
		}
		$text = $local ? "$text\n   Fehler trat auf vor: $local" : $text;
		$self->{string} = $self->{string} ? $self->{string} . "\n$text" : $text;
		$self;
	}
	sub string {shift->{string}}
	sub toXml {"<error>". shift->string . "</error>"}
	sub isError {1}
package lambda;
	$lambda::error::msgE{"analyze_01"} = "Keine Funktion gefunden! Signatur: &&1";
package lambda::base;
	sub isAtom {}
package lambda::atom;
	use vars ('@ISA');
	@ISA = qw (lambda::base);
	sub new {
		my $atom = bless {}, shift;
		my $value = shift;
		$atom->setValue ($value) if $value;
		$lambda::atoms {$atom->{id} = $atom->id} = $atom;
	}
	sub first {
		my $list = $_[0]->{value};
		$list && $list->isList ? $list->{first} : undef;
	}
	sub second {
		my $b = $_[0]->first;
		$b ? $b->{next} : undef
	}
	sub third {
		my $b = $_[0]->second;
		$b ? $b->{next} : undef;
	}
	sub fourth {
		my $b = $_[0]->third;
		$b ? $b->{next} : undef;
	}
	sub fifth {
		my $b = $_[0]->fourth;
		$b ? $b->{next} : undef
	}
	sub last {
		my $list = $_[0]->{value};
		$list && $list->isList ? $list->{last} : undef;
	}
	sub firsts {
		my $first = $_[0]->first;
		my @firsts = ($first);
		return @firsts if ! $first;
		my $n = $_[1];
		while (--$n) {
			$first = $first->{next};
			$first ? push @firsts, $first : last;
		}
		@firsts;
	}
	sub setPointer {
		my $atom = $_[0];
		my $list = $atom->{root}->{value};
		$list->{pointer} = $atom->{before};
		$list;
	}
	sub newAtomBefore {
		my $atom = $_[0];
		my $newAtom = lambda::atom->new (@_);
		my $before = $atom->{before};
		my $root = $atom->{root};
		if ($before) {
			$newAtom->{before} = $before;
			$before->{next} = $newAtom;
		} else {
			$root->{value}->{first} = $newAtom;
		}
		$newAtom->{root} = $root;
		$newAtom->{next} = $atom;
		$atom->{before} = $newAtom;
	}
	sub newAtomAfter {
		my $atom = $_[0];
		my $newAtom = lambda::atom->new (@_);
		my $next = $atom->{next};
		my $root = $atom->{root};
		if ($next) {
			$newAtom->{next} = $next;
			$next->{before} = $newAtom;
		} else {
			$root->{value}->{last} = $newAtom;
		}
		$newAtom->{root} = $root;
		$newAtom->{before} = $atom;
		$atom->{next} = $newAtom;
	}
	sub isQuoted {
		my $root = $_[0];
		while ($root) {
			return 1 if $root->{value}->{quote};
			$root = $root->{root};
		}
		undef;
	}
	sub blockFromScript {
		my ($atom, $myProperty) = @_;
		$atom->defSymbol ($lambda::my, $myProperty) if $myProperty;
		while (1) {
			return lambda::error->new (36) if ! $lambda::script;
			last if $lambda::script =~ s/^\s*\}\s*//;
			$lambda::script =~ /^\{/ ? atomFromScript ($atom) : listFromScript ($atom->appendAtom);
			return if $lambda::error;
		}
		return $lambda::undefined if $atom->isQuoted;
		delete $atom->{value}->{quote};
		analyze ($atom);
	}
	sub listFromScript {
		my $atom = shift;
		$atom->{value} = lambda::list->new;
		do {
			$lambda::script =~ s/^\s+//;
			return lambda::error->new (36) if ! $lambda::script;
			$lambda::script =~ /^'?\(/ ? subListFromScript ($atom->appendAtom) : atomFromScript ($atom);
			return if $lambda::error;
		} until ($lambda::script =~ s/^\s*;\s*// || $lambda::script =~ /^\s*}/);
		$atom->isQuoted ? $lambda::undefined : analyzeCommandList ($atom);
	}
	sub subListFromScript {
		my $atom = shift;
		my $list = $atom->{value} = lambda::list->new;
		my $bracket = $lambda::script =~ /^'?\(/;
		if ($bracket) {
			$list->{quote} = $lambda::script =~ s/^'//;
			$lambda::script =~ s/^\(//;
		}
		my $result;
		while (1) {
			$lambda::script =~ s/^\s+//;
			return lambda::error->new (36) if ! $lambda::script;
			if ($bracket) {
				return $atom->access if $lambda::script =~ s/^\)//;
			} elsif ($lambda::script =~ /^[;\}]/) {
				$lambda::script =~ s/^;//;
				return $lambda::undefined;
			}
			$lambda::script =~ /^'?\(/ ? subListFromScript ($atom->appendAtom) : atomFromScript ($atom);
			return if $lambda::error;
		}
	}
	sub specialSubListFromScript {
		my ($atom, $s1, $s2) = @_;
		my $list = $atom->{value} = lambda::list->new;
		$atom->appendValues (lambda::symbol->new ($s1));
		$lambda::script =~ s/.\s*//;
		while (1) {
			return lambda::error->new (36) if ! $lambda::script;
			my $first = substr ($lambda::script, 0, 1);
			last if $first eq $s2;
			if ($first eq "{") {
				$lambda::script =~ s/^.\s*//;
				$atom->appendAtom->blockFromScript;
			} elsif ($lambda::script =~ /^'?\(/) {
				subListFromScript ($atom->appendAtom);
			} elsif ($first eq $s1) {
				$lambda::script =~ s/^.\s*//;
				specialSubListFromScript ($atom->appendAtom, $s1, $s2);
			} else {
				$lambda::script =~ s/^\s*//;
				atomFromScript ($atom);
			}
			return if $lambda::error;
			$lambda::script =~ s/^\s+//;
		}
		$lambda::script =~ s/^$s2//;
		$atom->appendAtoms (lambda::symbol->new ($s2));
	}
	sub access {
		my $atom = shift;
		while ($lambda::script =~ s/^'//) {
			$lambda::script =~ s/(.*?)([';\(\)\[\]\{\}\s].*)/$2/;
			$atom = $atom->newAtomAfter->appendAtoms ($atom, "'$1");
			return if $lambda::error;
		}
		$lambda::undefined;
	}
	sub changeValues {
		my $atom = shift;
		my ($first, $second, $third) = $atom->firsts (3);
		my $property = $first->{return};
		my $value = $first->{value};
		my $class = $property->{class};
		while ($third->{next}) {
			my $new = $first->newAtomBefore;
			$new->appendAtoms ($first, $second, $third);
			$new->analyzeCommandList;
			return if $lambda::error;
			($first, $second, $third) = $atom->firsts (3);
		}
		$atom->analyzeCommandList;
		$property;
	}
	sub atomFromScript {
		my $root = shift;
		$lambda::script =~ s/^\s+//;
		return $lambda::undefined if ! $lambda::script || $lambda::script =~ s/^[\)\}\];]//;
		my $atom = $root->appendAtom;
		if ($lambda::script =~ /^\{/) {
			$lambda::script =~ s/^\{\s*//;
			$atom->{value} = $atom->{root}->{value}->isBlock ? lambda::commandBlock->new : lambda::dBlock->new;
			return $atom->blockFromScript;
		} elsif ($lambda::script =~ /^'?\(/) {
			subListFromScript ($atom);
			return $lambda::error ? undef : $atom->access;
		} elsif ($lambda::script =~ /^\[/) {
			specialSubListFromScript ($atom, "[", "]");
			return $lambda::error ? undef : $atom->access;
		} elsif ($lambda::script =~ s/^([sm]\/)([^\s])/$2/) {
			my $s = $1;
			return lambda::error->new (49, $s) if $lambda::script !~ s/^(.*?)\///;
			$s .= $1;
			while ($s =~ /\\$/) {
				return lambda::error->new (49, $s) if $lambda::script !~ s/^(.*?)\///;
				$s .= "/$1";
			}
			if ($s =~ /^s/) {
				return lambda::error->new (49, $s) if $lambda::script !~ s/^(.*?)\///;
				$s .= "/$1";
				while ($s =~ /\\$/) {
					return lambda::error->new (49, $s) if $lambda::script !~ s/^(.*?)\///;
					$s .= "/$1";
				}
			}
			return lambda::error->new (49, $s) if $lambda::script !~ /^([wgmixXsuUAjD]*)[\s;'\(\)\[\]\{\}]/;
			my $q = $1;
			$lambda::script =~ s/^$q// if $q;
			my $regex = $lambda::master::regExpr->new ("$s/$q");
			return if $lambda::error;
			$atom->appendValues ($regex);
		} elsif ($lambda::script =~ s/^"//) {
			return lambda::error->new (36) if $lambda::script !~ s/^(.*?)"//;
			my $s = $1;
			while ($s =~ s/\\$/"/) {
				return lambda::error->new (36) if $lambda::script !~ s/^(.*?)"//;
				$s .= $1;
			}
			return lambda::error->new (39, $s) if $lambda::script !~ /^[\s;'\(\)\[\]\{\}]/;
			$atom->{value} = (! $s || $s =~ /\s/) ? $lambda::master::string->new ($s) : $lambda::master::word->new ($s);
			return $atom->access;
		} else {
			my $quote = $lambda::script =~ s/^'//;
			return lambda::error->new (77) if $lambda::script =~ /^'/;
			$lambda::script =~ s/^(.*?)([\s\(\)\{\}\[\];'])/$2/;
			my $value = valueFromString ($1);
			return if $lambda::error;
			if ($quote) {
				$value->isSymbol ? ($value->{quote} = $quote) : (return lambda::error->new (71, $value));
			}
			$atom->{value} = $value;
			return $atom->access;
		}
		$lambda::undefined;
	}
	sub valueFromString {
		my $string = shift;
		my $value;
		if ($string =~ /^[+-]?[1-9]\d*$|^[+-]?0$/) {
			$value = $lambda::master::number->newFromString ($string);
		} elsif ($string =~ /^([+-]?[1-9]\d*)\/([1-9]\d*)$/) {
			$value = $lambda::master::number->newFromString ($1, $2);
		} elsif ($string =~ /^([+-]?)(\d+)[\.]?(\d*)[eE]?([+-]?)(\d+)?$/) {
			my $e = - length ($3);
			my $h = $2 . $3;
			$h = - $h if $1 eq "-";
			$e = ($4 && $4 eq "-" && $5) ? $e - $5 : $e + $5 if $5;
			$value = $e > 0 ? $lambda::master::number->newFromString ($h * ("1" . "0" x $e)) : $lambda::master::number->newFromString ($h, "1" . "0" x -$e);
		} elsif ($string =~ /^([sm]?)\/(.*)\/([gmixXsuUAjD]?)$/) {
			$value = $lambda::master::regExpr->new (($1 || "m") . "/$2/$3");
			my $test = "test";
			eval "\$test =~ " . $value->{value} . "\n";
			return lambda::error->new (49, $value) if $@;
		} elsif ($string =~ /^<([a-zA-Z]+)>$/) {
			$value = $lambda::master::xmlTag->new ($1);
		} elsif ($string =~ /^true$/) {
			$value = $lambda::true;
		} elsif ($string =~ /^false$/) {
			$value = $lambda::false;
		} elsif ($string eq "/") {
			return lambda::symbol->new ($string);
		} elsif ($string =~ /^([+-]?)(\d*?)\/?(\d*?)\/?(\d*?):?(\d*),?(\d*\.?\d*)$/ && $string !~ m/^[+-]$/) {
			$value = $lambda::master::timespan->new (((($3 || 0) * 24 + ($4 || 0)) * 60 + ($5 || 0)) * 60 + ($6 || 0), $2 || 0);
			if ($1 && $1 eq "-") {
				$value->{months} = - $value->{months};
				$value->{seconds} = - $value->{seconds};
			}
			$value = undef if $string !~ /\d/;
		} elsif ($string =~ /^.*\.lbd$/) {
			$value = $lambda::master::file->new ($string);
		} elsif ($string =~ /^(D|\d{1,2})([\.-])(M|\d{1,2})\2(Y|\d{1,4})$/) {
			my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
			$year = $4 < 100 ? $year + ($4 - $year % 100) : $4 if $4 ne "Y";
			$mon = $3 - 1 if $2 ne "M";
			$mday = $1 if $1 ne "D";
			eval {Time::Local::timelocal(0, 0, 0, $mday, $mon, $year)};
			return lambda::error->new (81, $string, $@) if $@;
			$value = $lambda::master::moment->new (Time::Local::timelocal (0, 0, 0, $mday, $mon, $year));
		} else {
			return lambda::symbol->new ($string);
		}
		$value->{constant} = 1;
		$value;
	}
	sub containConstant {
		my $v = shift->{value};
		$v->isValue && $v->{constant};
	}
	sub defSymbol {
		my ($atom, $symbol, $property) = @_;
		my $blockAtom = $atom->block;
		my $name = $symbol->{value};
		my $value = $property->{value};
		my $block = $blockAtom->{value};
		if ($symbol->{quote} || $value->isClass) {
			return $block->{properties}->{$name} ? lambda::error->new (21, $name) :
			($block->{properties}->{$name} = $property);
		}
		my $oldProperty = $blockAtom->findSymbol ($symbol);
		$oldProperty->isUndefined ? ($block->{properties}->{$name} = $property) : $oldProperty;
	}
	sub setTemp {
		my ($atom, $valueAtom) = @_;
		my $value = $valueAtom->{value};
		return $valueAtom->detach if $value->isSymbol || $value->{constant};
		my $tempSymbol = lambda::symbol->new;
		$atom->appendAtoms ("list");
		my $last = $atom->last;
		$last->appendAtoms ($tempSymbol, "==", $valueAtom);
		$last->analyzeCommandList;
		$lambda::error ? undef : $tempSymbol;
	}
	sub defProperty {
		my ($atom, $class, $name, $property, $rw) = @_;
		$rw = "rw" if ! $rw;
		$class->{properties}->{$name} = $property;
		my $propertyClass = $property->{class};
		my $className = $class->{name};
		$atom->addFunction ("data_getProperty", $property, $className, "'$name") if $rw =~ m/r/i;
		$property->{readOnly} = 1 if $rw !~ m/w/i;
		$property;
	}
	sub fixAnalyze {
		my ($atom, $name, $property) = @_;
		my $list = $atom->setPointer;
		my $function = $atom->changeCommand ($name);
		return $atom->{return} = $property if $property;
		my $action = $function->{init};
		$atom->{return} = $action ? $action->($atom) : $function->{return}->copy;
	}
	sub changeCommand {
		my ($atom, $name) = @_;
		$atom->{value}->{function} = $lambda::master->{functions}->{$name};
	}
	sub analyze {
		my $atom = shift;
		my $return = $atom->{return};
		return $return if defined $return;
		my $value = $atom->{value};
		if ($value->isSymbol) {
			return $atom->{return} = $value if $value->{quote};
			my $property = $atom->findSymbol ($value);
			return $atom->{return} = $property if ! $property->isUndefined;
			(my $function, $return) = $atom->searchFunction ($value->{value});
			return $atom->{return} = $value if ! $function->isFunction || $function->{return}->isUndefined;
			if ($atom->{next} || $atom->{before}) {
				$atom->appendAtoms ($value);
				$atom->first->{return} = $value;
				$atom->{value}->{function} = $function;
			}
		} elsif ($value->isClass || $value->isValue) {
			$return = lambda::property->new ($value->{class}, $value);
		} elsif ($value->isBlock) {
			$return = $lambda::undefined;
			my $next = $value->first;
			while ($next) {
				$return = analyze ($next);
				return if defined $lambda::error;
				$next = $value->next;
			}
		} elsif ($value->isFunctional) {
			delete $atom->{return};
			$return =analyzeCommandList ($atom);
			return if $lambda::error;
			$value->{quote} = 1;
			$return = lambda::property->new ($return->{class}, $value);
		} elsif ($value->isList) {
			$return = $atom->analyzeCommandList;
			return if defined $lambda::error;
		}
		$atom->{return} = $return;
	}
	sub analyzeCommandList {
		my $atom = shift;
		my $return = $atom->{return};
		return $return if $return;
		my $list = $atom->{value};
		my $isFunctional = $list->{quote};
		my ($first, $second, $third) = $atom->firsts (3);
		return $atom->{return} = $lambda::undefined if ! defined $first;
		my $s = "";
		if ($first->{value}->isQuotedList && $second->{value}->isSymbol (":=") && $third->{value}->isDefinitionBlock) {
			$s = "'list := 'block";
		} else {
			my $current = $list->first;
			while ($current) {
				my $value = $current->{value};
				if ($value->isDefinitionBlock) {
					$s .= " 'block";
				} else {
					my $return = $current->{return};
					if (! $return) {
						$return = $current->analyze;
						return if $lambda::error;
						if ($return->isSymbol) {
							if ($return->{quote}) {
								$current->{return} = $return;
							} else {
								my $property = $atom->findSymbol ($return);
								$current->{return} = $property->isProperty ?	$property : $return;
							}
						}
						$current = $list->current;
					}
					if ($return->isSymbol) {
						$s .= " " . $return->{value};
					} elsif ($return->isProperty) {
						my $value = $return->{value};
						my $class = $return->{class};
						if ($value->isClsClass) {
							$s .= " ''data''";
						} elsif ($class->isClsClass) {
							my $l = $value->qName;
							$l =~ s/(".*)//;
							$s .= " ''data'$l'";
						} elsif ($class->isClass) {
							$s .= $class->searchString;
						}
					}
				}
				$current = $list->next;
			}
		}
		$list->toFunctional if $isFunctional;
		(my $function, $return) = $atom->searchFunction ($s);
		return if $lambda::error;
		if ($function->isFunction) {
			$list->{function} = $function if ! defined $list->{function};
			return $return;
		}
		$s =~ s/'[^ ]*('[^ ]*')'/$1/g;
		lambda::error->new (1, "$s;");
	}
	sub searchFunction {
		my ($atom, $signature, $without) = @_;
		$signature =~ s/^\s+|\s+$//g;
		if ($signature) {
			my $block = $atom;
			do {
				$block = $block->block;
				foreach (grep {$signature =~ /$_->{search}/} @{$block->{value}->{functions}}) {
					next if $without && $_->{sub} && $without =~ /\b$_->{sub}\b/;
					my $return = $_->init ($atom);
					if ($lambda::error) {
						$signature =~ s/'[^ ]*('[^ ]*')'/$1/g;
						return lambda::error->new ("analyze_01", $signature) ;
					}
					next if $return->isEmpty;
					return ($_, $return);
				}
			} until ! ($block = $block->{root});
		}
		$lambda::undefined;
	}
	sub shiftAfter {
		my ($atom, $predecessor) = @_;
		my $list = $atom->{root}->{value};
		my $before = $atom->{before};
		my $next = $atom->{next};
		if ($before) {
			$next ? ($next->{before} = $before) : ($list->{last} = $before);
			$before->{next} = $next;
		} else {
			delete $next->{before} if $next;
			$list->{first} = $next;
		}
		$atom->{root} = $predecessor->{root};
		$atom->{before} = $predecessor;
		$next = $predecessor->{next};
		$next ? ($atom->{next} = $next) : ($predecessor->{root}->{value}->{last} = $atom);
		$predecessor->{next} = $atom;
		$atom;
	}
	sub appendAtom {
		my $root = shift;
		my $list = $root->{value};
		$list = $root->{value} = lambda::list->new if ! $list;
		if (! $list->isList) {
			$list->erase;
			$list = $root->{value} = lambda::list->new;
		}
		my $atom = lambda::atom->new;
		my $last = $list->{last};
		if ($last) {
			$last->{next} = $atom;
			$atom->{before} = $last;
		} else {
			$list->{first} = $atom;
		}
		$list->{last} = $atom;
		$atom->{root} = $root;
		$atom;
	}
	sub appendValues {
		my $atom = shift;
		$atom->insertAsLast ($_) foreach @_;
		$atom;
	}
	sub insertValues {
		my $atom = shift;
		my $value = $atom->{value};
		if (! $value || ! $value->isList) {
			$atom->{value} = lambda::list->new;
		} elsif ($value->{first}) {
			$value->erase;
		}
		$atom->insertAsLast ($_) foreach @_;
		$atom;
	}
	sub appendAtoms {
		my ($atom, @atoms) = @_;
		my $list = $atom->{value};
		$list = $atom->{value} = lambda::list->new if ! $list || ! $list->isList;
		undef $atom->{return};
		while (1) {
			my $s = shift @atoms;
			last if ! $s;
			if (! ref ($s)) {
				if ($s =~ / /) {
					@atoms = (split (" ", $s), @atoms);
				} elsif ($s eq "list") {
					$atom->appendValues (lambda::list->new);
				} elsif ($s eq "dBlock") {
					$atom->appendValues (lambda::dBlock->new);
					delete $atom->last->{value}->{quote};
				} elsif ($s eq "block") {
					$atom->appendValues (lambda::commandBlock->new);
				} else {
					my $last = $atom->appendAtom;
					$last->{value} = $last->{return} = lambda::symbol->new ($s, 1);
					return if $lambda::error;
				}
			} elsif ($s->isProperty) {
				my $last = $atom->appendAtom;
				$last->{value} = $s->{value};
				$last->{return} = $s;
			} elsif ($s->isValue) {
				my $last = $atom->appendAtom;
				$last->{value} = $s;
				$last->{return} = lambda::property->new ($s);
			} elsif ($s->isSymbol) {
				my $last = $atom->appendAtom;
				$last->{value} = $s;
				if ($s->{quote}) {
					$last->{return} = $s;
				} else {
					my $property = $atom->findSymbol ($s);
					$last->{return} = $property->isProperty ? $property : $s;
				}
			} elsif ($s->isAtom) {
				if ($s->{root}) {
					my $last = $list->{last};
					$s->extract;
					$list->{last} = $s;
					$list->{first} ? $last->{next} = $s : $list->{first} = $s;
					$s->{before} = $last;
					$s->{root} = $atom;
				} else {
					my $last = $atom->appendAtom;
					$last->setValue ($s->{value}, $s->{return});
				}
			}
		}
		$atom;
	}
	sub appendList {
		my ($atom, @atoms) = @_;
		my ($listAtom, $typ, $result);
		my $s = shift @atoms;
		return lambda::error->new (0, "Öffnende Klammer fehlt!") if ref $s;
		if ($s =~ s/^ *\(//) {
			$typ = "list";
			$listAtom = $atom->insertAsLast (lambda::list->new);
		} elsif ($s =~ s/^ *\{//) {
			$listAtom = $atom->insertAsLast (lambda::dBlock->new);
			$typ= "block";
		} else {
			return lambda::error->new (0, "Öffnende Klammer fehlt!");
		}
		$s = shift @atoms if ! $s;
		while (1) {
			if (ref ($s)) {
				$listAtom->appendAtoms ($s);
			} else {
				if (! $s) {
				} elsif ($s =~ s/^(.+)([\(\)\{\}])/$1 $2/g || $s =~ /\s/) {
					@atoms = (split (/\s+/, $s), @atoms);
				} elsif ($s =~ /^[\(\{]/) {
					($result, @atoms) = $listAtom->appendList ($s, @atoms);
					return if $lambda::error;
				} elsif ($s =~ s/^\)\s*//) {
					if ($typ eq "list") {
						unshift @atoms, $s if $s;
						last;
					} else {
						return lambda::error->new (0, "Keine offene Liste!");
					}
				} elsif ($s =~ s/^\}\s*//) {
					if ($typ eq "block") {
						unshift @atoms, $s if $s;
						last;
					} else {
						return lambda::error->new (0, "Kein offener Block!");
					}
				} else {
					$listAtom->appendAtoms ($s);
				}
			}
			return lambda::error->new (0, "Schließende Klammer fehlt!") if ! @atoms;
			$s = shift @atoms;
		}
		return $lambda::undefined if ! @atoms;
		$s = shift @atoms;
		return ($lambda::undefined, $s, @atoms) if ref $s;
		if ($typ eq "list") {
			if ($s =~ s/^#([^\s\(\)\{\}]*)//) {
				$result = $1 ? $listAtom->fixAnalyze ($1) : $listAtom->analyze;
			}
		} else {
			$result = $listAtom->analyze if $s =~ s/^#\s*//;
		}
		unshift @atoms, $s if $s;
		($result, @atoms);
	}
	sub insertAsFirst {
		my $atom = shift;
		my $list = $atom->{value};
		$list = $atom->{value} = lambda::list->new if ! $list;
		my $newAtom = lambda::atom->new;
		$newAtom->{root} = $atom;
		my $first = $list->{first};
		if ($first) {
			$list->{first} = $first->{before} = $newAtom;
			$newAtom->{next} = $first;
		} else {
			$list->{first} = $list->{last} = $newAtom;
		}
		$newAtom->setValue (@_);
		$newAtom;
	}
	sub insertAsLast {
		my $newAtom = shift->appendAtom;
		$newAtom->setValue (@_);
		$newAtom;
	}
	sub swap {
		my ($atom1, $atom2) = @_;
		my $list = $atom1->{root}->{value};
		my $before1 = $atom1->{before};
		my $before2 = $atom2->{before};
		if ($before1) {
			$before1->{next} = $atom2;
			$atom2->{before} = $before1;
		} else {
			$list->{first} = $atom2;
			delete $atom2->{before};
		}
		if ($before2) {
			$before2->{next} = $atom1;
			$atom1->{before} = $before2;
		} else {
			$list->{first} = $atom1;
			delete $atom1->{before};
		}
		my $next1 = $atom1->{next};
		my $next2 = $atom2->{next};
		if ($next1) {
			$atom2->{next} = $next1;
			$next1->{before} = $atom2;
		} else {
			$list->{last} = $atom2;
			delete $atom2->{next};
		}
		if ($next2) {
			$atom1->{next} = $next2;
			$next2->{before} = $atom1;
		} else {
			$list->{last} = $atom1;
			delete $atom1->{next};
		}
	}
	sub setValue {
		my ($atom, $value, $property) = @_;
		my $oldValue = $atom->{value};
		my $return = $atom->{return};
		if (! $oldValue || $oldValue ne $value) {
			$oldValue->erase if $oldValue && $oldValue->isList;
			$atom->{value} = $value;
			$property = lambda::property->new ($value) if $value->isValue && ! $property && ! $return;
			if ($value->isList) {
				my $next = $value->{first};
				while ($next) {
					$next->{root} = $atom;
					$next = $next->{next};
				}
			} elsif ($return) {
				$return->{value} = $value;
			}
		}
		$atom->{return} = $property if $property;
		$value;
	}
	sub repeatBlock {
		my ($atom, $block) = @_;
		my $blockAtom = $atom->newAtomBefore;
		$blockAtom->setValue ($block->copy->toCommandBlock, $lambda::undefined);
		$blockAtom->{quit} = 1;
		$lambda::pureEmpty;
	}
	sub evaluateBlock {
		my ($atom, $resolve) = @_;
		my $block = $atom->{value};
		my $result = $block->{result} ? $block->{result} : $lambda::undefined;
		$atom->containThread ? $atom->extract : $atom->erase if ! defined $block->first;
		while (my $current = $block->current) {
			my $isBlock = $current->{value}->isBlock;
			$result = $isBlock ? $current->evaluateBlock ($resolve) : $current->evaluateList ($resolve);
			return if defined $lambda::error;
			if ($result->isWait || $result->isTerminate) {
				return $result;
			} elsif ($result->isPureEmpty) {
			} elsif (! defined $current->{value}) {
			} elsif ($result->isQuit) {
				return $result->{blockId} eq $atom->{id} ? $lambda::undefined : $result;
			} else {
				$block->{result} = $result;
				$current->extract if ! $current->erase;
			}
		}
		delete $block->{result};
		$result;
	}
	sub evaluateList {
		my ($atom, $resolve) = @_;
		my $list = $atom->{value};
		return $lambda::undefined if ! $list->{first};
		my $result = $atom->interrupt;
		return $result if $result->isWait;
		my $function = $list->{function};
		$resolve = $function->{resolve} || $resolve;
		if ($resolve) {
			delete $list->{quote};
		} elsif ($list->{quote}) {
			return $lambda::undefined;
		}
		my $noResolve = $function->{noResolve};
		my @parameter = ();
		my $isFunctional;
		$list->first;
		while (my $current = $list->current) {
			my $value = $current->{value};
			while (1) {
				return if defined $lambda::error;
				$current = $list->current;
				if ($value->isSymbol) {
					my $return = $current->{return};
					last if $return->isSymbol;
					$value = $return->{value};
				} elsif ($value->isFunctional) {
					if ($noResolve) {
					} elsif ($resolve) {
						$value = $current->evaluateFunctional ($value);
					} else {
						$isFunctional = 1;
					}
					last;
				} elsif ($value->isCommandBlock) {
					$value = $current->evaluateBlock ($resolve);
				} elsif ($value->isDefinitionBlock) {
					last;
				} elsif ($value->isCommandList) {
					$value = $current->evaluateList ($resolve);
				} elsif ($value->isTerminate || $value->isWait) {
					return $value;
				} elsif ($value->isUndefined) {
					$current->extract if ! $current->erase;
					undef $value;
					last;
				} else {
					$current->setValue ($value) if ! ($current->{value}->isSymbol || $current->{value}->isCommandBlock);
					$current->{return}->{value} = $value;
					last;
				}
			}
			push @parameter, $value if defined $value;
			$list->next;
		}
		return $lambda::undefined if not scalar @parameter;
		$resolve || $noResolve || ! $isFunctional ? $function->call ($atom, @parameter) : $list->toFunctional;
	}
	sub evaluateFunctional {
		my $atom = shift;
		my $new = $atom->newAtomAfter;
		$new->setValue (shift->copy);
		my $value = $new->evaluateList (1);
		$new->erase;
		$value;
	}
	sub microScript {
		my ($atom, $script, @atoms) = @_;
		my $new = $atom->newAtomAfter;
		my $block = $new->{value} = lambda::commandBlock->new;
		my @symbols = ();
		my $k = 1;
		foreach (@atoms) {
			my $symbol = lambda::symbol->new ("&$k");
			$block->{properties}->{$symbol->{value}} = $_->{return}->copy;
			my $nr = $symbol->{value};
			my $new = $new->appendAtom->appendAtoms ($symbol, ":=", $_);
			$new->fixAnalyze ("value_changeValue");
			$k++;
		}
		$atom->erase;
		push @lambda::script, $lambda::script;
		$lambda::script = "$script}";
		my $microScript = $lambda::microScript;
		$lambda::microScript = 1;
		$new->blockFromScript;
		$lambda::microScript = $microScript;
		$lambda::script = shift @lambda::script;
		$new->{return};
	}
	sub interrupt {
		use constant interruptTime => 250;
		my $thread = shift->thread;
		return $lambda::undefined if $thread->{term}->stepTerm < $main::lambda_interruptTime;
		$thread->{priority} += 5;
		my $wait = $thread->{wait} = lambda::await->new;
		my $waitAtom = $wait->{atom} = $thread->insertAsFirst (lambda::list->new);
		$waitAtom->{return} = lambda::property->new ($lambda::master::number->new);
		$wait->{index} = 0;
		$wait->{time} = lambda::waitPoint->new (interruptTime / 1000 + Time::HiRes::gettimeofday (), 1);
		my $hash = $thread->lambda->{hash};
		main::Log3 ($hash, 4, $hash->{NAME} . " interrupted for " . interruptTime . " ms!");
		$lambda::wait;
	}
	sub findSymbol {
		my ($atom, $symbol) = @_;
		my $name = $symbol->{value};
		my $isolate;
		while (1) {
			$atom = $atom->block;
			my $property = $atom->{value}->{properties}->{$name};
			if (defined $property) {
				my $value = $property->{value};
				return $property if ! $isolate || $value->isClass || $value->isA ($lambda::master::device);
			}
			if ($atom->isMaster) {
				return $main::defs{$name} ? $lambda::master->getDevice ($name) : $lambda::undefined;
			} else {
				$isolate = 1 if $atom->{isolate};
				$atom = $atom->{root};
			}
		}
	}
	sub findClass {
		my ($atom, $name) = @_;
		my $property = $atom->findSymbol (lambda::symbol->new ($name));
		return $property if $property->isUndefined;
		my $class = $property->{value};
		$class->isClass ? $class : $lambda::undefined;
	}
	sub containCommands {
		my $block = shift->{value};
		return undef if ! ($block && $block->isBlock);
		my $first = $block->{first};
		while ($first) {
			return 1 if ! $first->containCommands;
			$first = $first->{next};
		}
		return undef;
	}
	sub containThread {
		my $atom = shift;
		my $value = $atom->{value};
		if ($value && $value->isList) {
			my $id = $atom->{id};
			my $topThread = $atom->thread;
			return undef if ! $topThread;
			my $topThreadId = $topThread->{id};
			foreach my $root ($topThread->subThreads) {
				while (1) {
					$root = $root->{root};
					my $rootId = $root->{id};
					return 1 if $rootId == $id;
					last if $rootId == $topThreadId
				}
			}
		}
		undef;
	}
	sub erase {
		my $atom = shift;
		return undef if $atom->{root} && $atom->containThread;
		if (! defined $atom->{id}) {
			main::Log3 (undef, 0, $atom);
			die;
		}
		delete $lambda::atoms {$atom->{id}};
		if (my $value = $atom->extract->{value}) {
			$value->erase if $value->isList;
			$atom->{value} = lambda::commandBlock->new if $atom->isLambda;
		}
		delete $atom->{return};
		delete $atom->{extracted};
		delete $atom->{value};
		delete $atom->{root};
		delete $atom->{quit};
		delete $atom->{id};
		return 1;
	}
	sub detach {
		my $atom = shift;
		$atom = $atom->extract;
		return $atom if $atom->isPureEmpty;
		my $value = $atom->{value};
		delete $atom->{value};
		$atom->erase;
		$value;
	}
	sub extract {
		my $atom = shift;
		my $id = $atom->{id};
		my $root = $atom->{root};
		return $atom if $atom->isThread;
		my $list = $root->{value};
		return $lambda::pureEmpty if ! $list;
		my $before = $atom->{before};
		my $next = $atom->{next};
		if ($list->isList) {
			my $first = $list->{first};
			while (1) {
				return $atom if ! $first;
				last if $first->{id} == $id;
				$first = $first->{next};
			}
			my $pointer = $list->{pointer};
			$list->{pointer} = $before if $pointer && $pointer eq $atom;
			$list->{last} = $before if ! $next;
			$list->{first} = $next if ! $before;
		}
		if ($before) {
			if ($next) {
				$before->{next} = $next;
				$next->{before} = $before;
				delete $atom->{next};
			} else {
				delete $before->{next};
			}
			delete $atom->{before};
		} elsif ($next) {
			delete $atom->{next};
			delete $next->{before};
		}
		$atom->{extracted} = 1;
		$atom;
	}
	sub addFunctions {
		my $atom = shift;
		my $property;
		while (@_) {
			my ($call, $class, $signatur) = (shift, shift, shift);
			if ($class eq ".") {
				$property = $lambda::undefined;
			} elsif ($class eq "class") {
				$property = lambda::property->new ($lambda::master::class);
			} else {
				my $class = $atom->findClass ($class);
				$property = lambda::property->new ($class);
			}
			addFunction ($atom, $call, $property, split (/,/, $_)) foreach split (/;/, $signatur);
		}
	}
	sub addFunction {
		my $blockAtom = shift->block;
		my $function = lambda::function->new ($blockAtom, @_);
		return if $lambda::error;
		my $block = $blockAtom->{value};
		my @functions = @{$block->{functions}};
		unshift @functions, $function;
		$block->{functions} = \@functions;
		$function;
	}
	sub lambda {
		my $atom = $_[0];
		$atom->isLambda ? (return $atom) : ($atom = $atom->{root}) while 1;
	}
	sub thread {
		my $atom = $_[0];
		$atom->isThread ? (return $atom) : ($atom = $atom->{root}) while 1;
	}
	sub block {
		my $atom = $_[0];
		$atom->{value}->isBlock ? (return $atom) : ($atom = $atom->{root}) while 1;
	}
	sub findLoop {
		my $root = $_[0];
		while (1) {
			return $root if $root->{quit} || $root->isThread;
			$root = $root->{root};
		}
	}
	sub string {
		my $atom = $_[0];
		my $value = $atom->{value};
		$value ? ((ref $value) eq "HASH" ? "[hash]" : ("[" . $value->string . "]")) : "[]";
	}
	sub toScriptXml {
		my $atom = $_[0];
		my $value = $atom->{value};
		return $value->toScriptXml if $value->isList;
		my $return = $atom->{return};
		return $value->toScriptXml if ! $return || $return->isUndefined || $return->isSymbol;
		my $s;
		my $valueR = $return->{value};
		my $class = $return->{class};
		my $t = "Klasse: " . $class->{name} . "<br />";
		my $v = $valueR->string;
		$v =~ s/^\{|\}//;
		if ($valueR->isDevice) {
			$s = $value->toScriptXml ("popup device");
			$v = $valueR->{value};
		} elsif ($valueR->isClass) {
			$s = $value->toScriptXml ("popup class");
		} else {
			$s = $value->toScriptXml ("popup value");
		}
		$t .= " Wert: $v";
		$t = "<span>$t</span></span>";
		$s =~ s/<\/span>$/$t/;
		$s
	}
	sub isAtom {1}
package lambda::term;
	use vars ('@ISA');
	@ISA = qw (lambda::base);
	sub new {
		my $self = bless {}, shift;
		$self->{firstStart} = $self->{runTime} = $self->{stepStart} = 0;
		$self;
	}
	sub start {
		my $self = shift;
		my $t = $self->{stepStart} = Time::HiRes::gettimeofday ();
		$self->{firstStart} = $t if !$self->{firstStart};
	}
	sub stop {
		my $self = shift;
		if ($self->{stepStart}) {
			$self->{runTime} += Time::HiRes::gettimeofday () - $self->{stepStart};
			$self->{stepStart} = 0;
		}
	}
	sub stepTerm {
		my $self = shift;
		$self->{stepStart} ? Time::HiRes::gettimeofday () - $self->{stepStart} : 0;
	}
	sub totalTerm {
		my $self = shift;
		$self->{runTime} + $self->stepTerm;
	}
	sub totalTime {
		my $self = shift;
		$self->{firstStart} ? Time::HiRes::gettimeofday () - $self->{firstStart} : 0;
	}
package lambda::thread;
	use vars ('@ISA');
	@ISA = qw (lambda::atom);
	sub new {
		my $thread = bless lambda::atom->new (lambda::commandBlock->new), shift;
		$thread->{priority} = 0;
		my $root = shift;
		if (my $atom = $root) {
			my $block = $atom->block;
			my $rootThread = $block->thread;
			$rootThread->{threads}->{$thread->{id}} = 1;
			$thread->{root} = $block;
		}
		$thread->{totalTerm} = lambda::term->new;
		$thread->{term} = lambda::term->new;
		$thread->{wait} = lambda::await->new;
		my %t = ();
		$thread->{threads} = \%t;
		$thread;
	}
	sub start {
		my $thread = shift;
		$thread->{wait}->initialize;
		$thread->{term}->start;
		$thread->lambda->{totalTerm}->start;
		$lambda::master->{totalTerm}->start;
		$thread->{priority}++;
		undef $lambda::error;
		my $result = $thread->evaluateBlock;
		return if defined $lambda::error;
		$thread->{priority}-- if $thread->{priority};
		if ($result->isWait) {
		} elsif ($result->isTerminate) {
			$thread->{ready} = 1;
			$_->{ready} = 1 foreach $thread->allSubThreads;
		} elsif (! $thread->containCommands) {
			$thread->{ready} = 1;
		}
		$result;
	}
	sub stop {
		my $thread = shift;
		$thread->{term}->stop;
		$thread->lambda->{totalTerm}->stop;
		$lambda::master->{totalTerm}->stop;
	}
	sub subThreads {
		my $thread = shift;
		my @threads = ();
		foreach (keys %{$thread->{threads}}) {
			my $subThread = $lambda::atoms {$_};
			if ($subThread->{ready} && ! ($subThread->containThread || $subThread->isLambda)) {
				$subThread->erase;
			} else {
				push @threads, $subThread;
			}
		}
		@threads;
	}
	sub containThread {
		scalar keys %{shift->{threads}} ? 1 : undef;
	}
	sub allSubThreads {
		my $thread = shift;
		my @threads = ();
		my @subThreads = $thread->subThreads;
		@threads = (@threads, $_->allSubThreads) foreach @subThreads;
		$thread->isMaster ? @threads : (@threads, $thread);
	}
	sub erase {
		my $thread = shift;
		$_->erase foreach $thread->subThreads;
		if (my $root = $thread->{root}) {
			delete $root->thread->{threads}->{$thread->{id}};
			while (! ($root->isThread || $root->containCommands || $root->containThread)) {
				my $root1 = $root->{root};
				$root->erase;
				$root = $root1;
			}
		}
		delete $thread->{threads};
		delete $thread->{wait};
		delete $thread->{term};
		delete $thread->{totalTerm};
		delete $thread->{priority};
		delete $thread->{ready};
		lambda::atom::erase ($thread);
	}
	sub putChangedProperty {
		my ($rootThread, $property) = @_;
		foreach ($rootThread->allSubThreads) {
			my $wait = $_->{wait};
			next if $wait->{index};
			my $atom = $wait->{atom};
			foreach my $waitPoint (@{$wait->{waitPoints}}) {
				my $waitProperty = $waitPoint->{value};
				next if ! $waitProperty->dependOn ($property);
				if ($waitProperty->{value}->isList) {
					next if ! $atom->evaluateFunctional ($waitProperty->{value})->compare ($waitPoint->{oldValue});
				}
				my $index = $wait->{index} = $waitPoint->{index};
				$atom->{return}->{value} = $atom->{value} = $lambda::master::number->newFromString ($index);
				last;
			}
		}
	}
	sub isThread {1}
package lambda;
	$lambda::error::msgE{"master_01"} = "Fehlender TYPE in &&1.";
package lambda::base;
	sub isMaster {}
package lambda::master;
	use vars ('@ISA');
	@ISA = qw (lambda);
	sub new {
		return $lambda::master if $lambda::master;
		my ($className, $hash) = @_;
		$hash->{helper}->{lambda} = $lambda::master = bless lambda::thread->new, $className;
		$lambda::master->{hash} = $hash;
		our $class = addClass (lambda::clsClass->new);
		our $value = addClass ($class->newClass ("value"));
		our $record = addClass ($value->newClass ("record"));
		our $task = addClass ($value->newClass ("task"));
		our $file = addClass ($value->newClass ("file"));
		our $string = addClass ($value->newClass ("string"));
		$lambda::emptyString = $string->new ("");
		$lambda::blank = $string->new (" ");
		our $word = addClass ($string->newClass ("word"));
		our $regExpr = addClass ($value->newClass ("regExpr"));
		our $number = addClass ($value->newClass ("number"));
		$lambda::one = $number->new (lambda::integer->new (0, 1));
		$lambda::ten = $number->new (lambda::integer->new (0, 10));
		our $unitOfMeasurement = addClass ($value->newClass ("unitOfMeasurement"));
		our $measurement = addClass ($number->newClass ("measurement"));
		our $boolean = addClass ($value->newClass ("boolean"));
		$lambda::true = $boolean->new (1);
		$lambda::false = $boolean->new (0);
		our $moment = addClass ($value->newClass ("moment"));
		our $stack = addClass ($value->newClass ("stack"));
		our $collection = addClass ($value->newClass ("collection"));
		our $vector = addClass ($value->newClass ("vector"));
		our $timespan = addClass ($value->newClass ("timespan"));
		our $fhemReading = addClass ($value->newClass ("fhemReading"));
		our $device = addClass ($value->newClass ("device"));
		our $fhemDevice = addClass ($device->newClass ("fhemDevice"));
		our $fhemLambdaDevice = addClass ($fhemDevice->newClass ("fhemLambdaDevice"));
		our $fhemHomematicDevice = addClass ($fhemDevice->newClass ("fhemHomematicDevice"));
		our $astronomy = addClass ($value->newClass ("astronomy"), main::AttrVal ("global", "longitude", "11"), main::AttrVal ("global", "latitude", "52"));
		our $xmlTag = addClass ($value->newClass ("xmlTag"));
		our $xmlElement = addClass ($stack->newClass ("xmlElement"));
		our $html5 = addClass ($value->newClass ("html5"));
		push (our @functions0, qw (
			isA boolean value,isA,class
			type class value,type
			master_verbose . verbose,number;
			master_repeat . repeat,@block
			master_thread . thread,(value),@block
			master_always . always,(value),@block
			master_defineCommand . @list,:=,@block
			master_encapsulate . encapsulate,(value),@block
			master_devices . devices;
			loop . loop
			master_quit . quit
			master_waitBlock . wait,value,(value),@block,(value,(value),@block);wait,value,(value),@block,(value,(value),@block),value,(value)
			master_wait number wait,value,(value)
			value_modify . value,@symbol,data,(@symbol,data)
			value_formula . -@,value#,|@&@=@!=@<=@<@=>@>@<=>@<>@~@!~@+@-@*@/@^@,value#,(|@&@=@!=@<=@<@=>@>@<=>@<>@~@!~@+@-@*@/@^@,value#)
		));
		push (our @functions1, qw (
			value_clone . value,copy;value,copy,class
			device_overwrite . device,:=,@*
		));
		$lambda::master->addFunctions (@functions0, our @functions, @functions1);
		foreach (@{$lambda::master->{value}->{functions}}) {
			my $sub = $_->{sub};
			$lambda::master->{functions}->{$sub} = $_;
			$_->{noResolve} = "master_wait class_modClass value_changeValue" =~ /\b$sub\b/;
			$_->{resolve} = "master_wait value_evaluate data_system data_log1 data_out fhemDevice_setReading" =~ /\b$sub\b/;
		}
		$lambda::master->{totalTerm} = lambda::term->new;
		$lambda::master;
	}
	sub addClass {
		my ($class, @init) = @_;
		my $rootClass = $class->isClass ? $lambda::master::class : undef;
		$lambda::master->{value}->{properties}->{$class->{name}} = lambda::property->new ($rootClass, $class);
		$class->init (@init);
		$class->{internally} = 1 if $class->{name} ne "value";
		$class;
	}
	sub erase {1}
	sub getDevice {
		my ($master, $name) = @_;
		my $property = $master->{value}->{properties}->{$name};
		return $property if $property;
		my $hash = $main::defs {$name};
		my $type = $hash->{TYPE};
		return lambda::error->new ("master_01", $name) if ! $type;
		my $device;
		if ($type eq "lambda") {
			$device = $lambda::master::fhemLambdaDevice->new ($name);
		} elsif ($type eq "CUL_HM") {
			$device = $lambda::master::fhemHomematicDevice->new ($name);
		} else {
			$device = $lambda::master::fhemDevice->new ($name);
		}
		$device->saveDB;
		$master->{value}->{properties}->{$name} = lambda::property->new ($device);
	}
	sub delDevice {
		my ($master, $name) = @_;
		my $hash = $main::defs {$name};
		return undef if ! $hash;
		main::lambda_Set ($hash, $name, "stop") if $hash->{TYPE} eq "lambda";
		delete $master->{value}->{properties}->{$name};
	}
	sub go {
		while (1) {
			my $thread = $lambda::master->findThread;
			if (! defined $thread) {
				return undef;
			} elsif ($thread->isMoment) {
				return $thread->{value};
			} elsif ($thread->isThread) {
				my $lambda = $thread->lambda;
				my $hash = $lambda->{hash};
				main::lambda_State ($hash, "running");
				my $result = $thread->start;
				main::readingsSingleUpdate ($lambda::master->{hash}, "atoms", scalar keys %lambda::atoms, 1);
				if ($lambda::error) {
					main::Log3 ($hash->{NAME}, 0, $lambda::error->string);
					return main::lambda_Stop ($hash, "aborted");
				} elsif ($thread->{ready}) {
					next if $thread->isLambda && $hash->{ROOT};
					if (! $thread->containThread) {
						return main::lambda_Stop ($hash, "finished") if $thread->isLambda;
						$thread->erase;
					}
				}
			}
		}
	}
	sub findThread {
		my @threads = sort {$a->{priority} <=> $b->{priority}} (grep {! $_->{ready}} $lambda::master->allSubThreads);
		my $minWaitTimeValue;
		my $now = Time::HiRes::gettimeofday ();
		foreach my $thread (@threads) {
			my $await = $thread->{wait};
			return $thread if $await->{index};
			my $waitTime = $await->{time};
			if ($waitTime) {
				my $waitTimeValue = $waitTime->{value};
				if ($waitTimeValue <= $now) {
					my $atom = $await->{atom};
					my $nWait = $atom->{value} = $lambda::master::number->newFromString ($waitTime->{index});
					$atom->{return}->changeValue ($nWait, $lambda::master);
					return $thread;
				} elsif (! $minWaitTimeValue || $waitTimeValue < $minWaitTimeValue) {
					$minWaitTimeValue = $waitTimeValue;
				}
			}
		}
		$minWaitTimeValue ? $lambda::master::moment->new ($minWaitTimeValue) : undef;
	}
	sub isMaster {1}
package lambda::init;
	use vars ('@ISA');
	@ISA = qw (lambda::atom);
	sub _isolateBlock {
		my $atom = shift;
		my ($first, $second) = $atom->firsts (2);
		my $symbolAtom = $second;
		my $blockAtom = $atom->last;
		if ($blockAtom->{id} eq $symbolAtom->{id}) {
			$blockAtom->{isolate} = 1;
			$blockAtom->analyze;
			return if $lambda::error;
			return $blockAtom;
		}
		my $lastSymbol = $blockAtom->{before};
		my $block = $blockAtom->{value};
		my @symbols = ();
		while (1) {
			my $symbol = $symbolAtom->{value};
			my $name = $symbol->{value};
			push @symbols, $name;
			return lambda::error->new (55, $symbol) if ! $symbol->isSymbol || $symbol->{quote};
			my $property = $block->{properties}->{$name} = $atom->findSymbol ($symbol);
			return lambda::error->new (20, $symbol) if $property->isUndefined;
			last if $symbolAtom eq $lastSymbol;
			$symbolAtom = $symbolAtom->{next};
		}
		$blockAtom->analyze;
		return if $lambda::error;
		my $properties = $block->{properties};
		foreach (@symbols) {
			delete $properties->{$_};
			$atom->second->erase;
		}
		@symbols = ();
		$blockAtom;
	}
	sub master_thread {
		my $atom = shift;
		my $block = _isolateBlock ($atom);
		return if $lambda::error;
		$atom->{return} = lambda::property->new ($lambda::master::task);
	}
	sub master_encapsulate {
		_isolateBlock (@_);
		$lambda::undefined;
	}
	sub master_devices {
		my $value = $lambda::master::stack->new ();
		$value->{properties}->{of} = lambda::property->new ($lambda::master::class, $lambda::master::device);
		lambda::property->new ($value);
	}
	sub master_waitBlock {
		my $atom = shift;
		my ($op, $first) = $atom->firsts (2);
		my $wait1 = $atom->newAtomAfter;
		my $call = $wait1->newAtomAfter;
		my $symbol = $atom->block->{value}->temp (lambda::property->new ($lambda::master::number));
		$wait1->appendAtoms ($symbol, ":= list");
		my $wait = $wait1->last;
		$wait->appendAtoms ($op);
		$call->appendAtoms ("if");
		my $n = 0;
		while ($first) {
			if ($first->{value}->isBlock) {
				$call->appendList("(", $symbol, "<=", $lambda::master::number->newFromString ($n), ")#number_le");
				$call->appendAtoms ($first);
			} else {
				$n++;
				$wait->appendAtoms ($first);
			}
			$first = $atom->first;
		}
		$wait->fixAnalyze ("master_wait");
		$wait1->fixAnalyze ("value_changeValue");
		$call->fixAnalyze ("boolean_ifBlock");
		$atom->erase;
		$lambda::undefined;
	}
	sub master_defineCommand {
		my $atom = shift;
		my ($param, $op, $command) = $atom->firsts (3);
		my $code = $command->{value};
		$command->{isolate} = 1;
		my @signatur;
		my @parameter;
		my $vars = $param->{value};
		my $var = $vars->first;
		while ($var) {
			my $p = $var->{value};
			if ($p->isSymbol) {
				my $result = $var->analyze;
				return lambda::error->new (2, $p) if ! $var->{return}->isSymbol;
				push @parameter, "";
				push @signatur, $p->{value};
			} elsif ($p->isList) {
				my ($first, $second) = $var->firsts (2);
				my $result = $first->analyze;
				return if $lambda::error;
				return lambda::error->new (69, $p) if ! $result->isProperty;
				my $class = $result->{value};
				return lambda::error->new (19, $p, $vars) if ! $class->isClass;
				return lambda::error->new (9, $p, $vars) if ! $second;
				my $symbol = $second->{value};
				return lambda::error->new (9, $symbol, $vars) if ! $symbol->isSymbol;
				my $name = $symbol->{value};
				push @parameter, $name;
				push @signatur, $class->{name};
				$code->{properties}->{$name} = lambda::property->new ($class);
			} else {
				return lambda::error->new (19, $p, $vars);
			}
			$var = $vars->next;
		}
		$command->analyze;
		return if $lambda::error;
		$code->{parameter} = \@parameter;
		my $function = $atom->addFunction ($code, $command->{return}, @signatur);
		foreach (@parameter) {
			my $parameter = $code->{properties}->{$_};
			next if ! $parameter;
			my $dev = $function->{devices}->{$parameter};
			delete $function->{devices}->{$dev} if $dev;
		}
		$command->{value} = $lambda::my;
		$atom->erase;
		$lambda::undefined;
	}
	sub evaluate {
		shift->first->analyze;
	}
	sub master_always {
		my $atom = shift;
		my $first = $atom->first;
		$first->{value}->{value} = "'thread";
		$first->{return} = $first->{value};
		my $blockAtom = $atom->last;
		$atom->appendAtoms ("dBlock");
		$atom->last->appendAtoms ("list");
		$atom->last->first->appendAtoms ("repeat", $blockAtom);
		$atom->fixAnalyze ("master_thread");
	}
	sub master_repeat {
		shift->last->analyze;
		$lambda::undefined;
	}
package lambda::command;
	use vars ('@ISA');
	@ISA = qw (lambda::atom);
	sub master_verbose {
		my ($atom, $op, $number) = @_;
		return lambda::error->new (17, "Null", $number) if ! $number->isNotNegInteger;
		$atom->block->{value}->{verbose} = $number->string;
		$lambda::undefined;
	}
	sub type {
		$_[1]->{class};
	}
	sub isA {
		my ($atom, $data, $op, $class) = @_;
		$data->isA ($class->{name}) ? $lambda::true : $lambda::false;
	}
	sub verbose {
		my $v = main::AttrVal (shift->lambda->{hash}->{NAME}, "verbose", "-1");
		$v = main::AttrVal ("global", "verbose", "0") if $v < 0;
		$lambda::master::number->new ($v);
	}
	sub master_wait {
		my $atom = shift;
		my $now = Time::HiRes::gettimeofday ();
		my $await = $atom->thread->{wait};
		my $index = 0;
		my @waitPoints = ();
		my @devices = ();
		my $isWaiting;
		my $next = $atom->second;
		while ($next) {
			++$index;
			my $property = $next->{return};
			my $value = $property->{value};
			if (! $value->isEmpty) {
				$value = lambda::command::moment_plus ($atom, $lambda::master::moment->new ($now), $value) if $value->isTimespan;
				if ($value->isMoment) {
					my $time = $value->{value};
					if ($time > $now) {
						my $T = $await->{time};
						if (! $T || ($T->{value} > $time)) {
							$await->{time} = lambda::waitPoint->new ($time, $index);
							$isWaiting = 1;
						}
					}
				} else {
					my $waitPoint = lambda::waitPoint->new ($property, $index);
					push @waitPoints, $waitPoint;
					if ($value->isFunctional) {
						$waitPoint->{oldValue} = $next->evaluateFunctional ($value);
						my %p = ();
						lambda::addInFunktionalProperties ($value->{properties} = \%p, $value);
						$next->{value} = $lambda::undefined;
					}
					@devices = (@devices, $value->includedDevices);
					$isWaiting = 1;
				}
			}
			$next = $next->{next};
		}
		my $zero = $lambda::master::number->new;
		return $zero if ! $isWaiting;
		my $new = $atom->newAtomAfter->appendAtoms ($zero);
		my $first = $await->{atom} = $new->first;
		$first->{value} = lambda::symbol->new ("'wait");
		$new->fixAnalyze ("data_value", $first->{return});
		$await->{waitPoints} = \@waitPoints;
		$await->{devices} = \@devices;
		$await->{index} = 0;
		$atom->erase;
		$lambda::wait;
	}
	sub master_encapsulate {
		my $atom = shift;
		my $blockAtom = $atom->last->shiftAfter ($atom)->{value}->toCommandBlock;
		$lambda::undefined;
	}
	sub master_repeat {
		my ($atom, $op, $block) = @_;
		$atom->repeatBlock ($block);
	}
	sub master_thread {
		my $atom = shift;
		$atom->first->erase;
		my $thread = lambda::thread->new ($atom);
		$thread->setValue ($atom->first->detach->toCommandBlock);
		$lambda::master::task->new ($thread);
	}
	sub master_quit {
		my $block = shift->findLoop;
		$block->{next}->erase;
		lambda::quit->new ($block);
	}
	sub master_devices {
		my $value = shift->{return}->{value};
		my @stack = ();
		while (my ($key, $v) = each %{$lambda::master->{value}->{properties}}) {
			my $d = $v->{value};
			push @stack, $d if $d->isDevice;
		}
		$value->{value} = \@stack;
		$value;
	}
package lambda::base;
	sub isList {}
	sub isQuotedList {}
	sub isCommandList {}
package lambda::list;
	use vars ('@ISA');
	@ISA = qw (lambda::base);
	sub first {
		my $list = shift;
		delete $list->{pointer};
		$list->{first};
	}
	sub current {
		my $list = shift;
		my $pointer = $list->{pointer};
		$pointer ? $pointer->{next} : $list->{first};
	}
	sub next {
		my $list = shift;
		$list->{pointer} = $list->current;
		$list->current;
	}
	sub erase {
		my $list = shift;
		delete $list->{pointer};
		delete $list->{number};
		delete $list->{function};
		my $properties = $list->{properties};
		if ($properties) {
			delete $properties->{$_} foreach keys %{$properties};
			delete $list->{properties};
		}
		$list->eraseAllAtoms;
	}
	sub eraseAllAtoms {
		my $list = shift;
		while (my $first = $list->{first}) {
			$first->erase;
		}
	}
	sub string {
		my ($list, $isSublist) = @_;
		my $next = $list->{first};
		my $atom = $next->{root};
		my $block = $atom->{root}->{value}->isBlock if $atom && $atom->{root} && $atom->{root}->{value};
		$block = $block || ! $isSublist;
		my $l = " ";
		while ($next) {
			my $value = $next->{value};
			my $s = "NIL";
			if (! $value) {
			} elsif ($value->isList) {
				$s = $value->string ($value->isList);
				$s =~ s/^\s+|\s+$//g if ! ($value->isBlock || $value->{quote})
			} elsif ($value->isString || $value->isWord) {
				$s = "\"" . $value->string . "\"";
			} else {
				$s = $value->string;
			}
			$l .= "$s ";
			$next = $next->{next};
		}
		$l =~ s/^\s+|\s+$//g;
		$l = $block && ! $list->{quote}? "$l;" : "($l)";
		my $f = $list->{function};
		$l .= "   " . $f->string ."\n" if $f;
		$list->{quote} ? "'$l" : $l;
	}
	sub getData {
		my $list = shift;
		my $first = $list->{first};
		return $lambda::pureEmpty if ! $first;
		return $list if $first->{next};
		my $value = $first->{value};
		return $list if $value->isSymbol;
		$value->getData;
	}
	sub copy {
		my ($list, $newProperties) = @_;
		my $newList = listCopy ($list, $newProperties);
		$newList->{function} = $list->{function};
		$newList->{quote} = $list->{quote};
		$newList;
	}
	sub listCopy {
		my ($list, $newProperties) = @_;
		my $newList = bless {}, ref $list;
		my $last;
		my $next = $list->{first};
		while ($next) {
			my $return = $next->{return};
			if ($newProperties && $return->isProperty) {
				my $id = $return->{id};
				my $newProperty = $newProperties->{$id};
				if ($newProperty) {
					$return = $newProperty;
				} else {
					$return = $newProperties->{$id} = $return->copy;
				}
			}
			my $new = lambda::atom->new;
			if ($last) {
				$last->{next} = $new;
				$new->{before} = $last;
			} else {
				$newList->{first} = $new;
			}
			$newList->{last} = $new;
			$last = $new;
			my $value = $next->{value};
			$value = $value->isList ? $value->copy ($newProperties) : $value->copy;
			$new->setValue ($value, $return);
			$next = $next->{next};
		}
		$newList->{quote} = $list->{quote};
		$newList;
	}
	sub changeAllProperties {
		my ($list, $old, $new) = @_;
		my $first = $list->{first};
		while ($first) {
			$first->{return} = $new if $first->{return} eq $old;
			my $value = $first->{value};
			$value->changeAllProperties ($old, $new) if $value->isList;
			$first = $first->{next};
		}
	}
	sub includedDevices {
		my @devices = ();
		my $first = shift->{first};
		while ($first) {
			my $property = $first->{return};
			if ($property->isProperty) {
				my $value = $property->{value};
				@devices = (@devices, $value->includedDevices) if $value->isValue;
			}
			$first = $first->{next};
		}
		@devices;
	}
	sub isList {1}
	sub isCommandList {1}
	sub isQuotedList {shift->{quote}}
	sub toFunctional {
		my $list = shift;
		delete $list->{quote};
		bless $list, "lambda::functional";
	}
	sub toScriptXml {
		my ($list, $class) = @_;
		$class = "list" if ! $class;
		my $next = $list->{first};
		my $sublist = ! $next->{root}->{root}->{value}->isBlock;
		my $etag;
		my $s;
		if ($sublist) {
			$s = "<span class=\"$class\">";
			$etag = "</span>";
		} else {
			$s = "<div class=\"$class\">\n";
			$etag = "\n</div>";
		}
		while ($next) {
			my $value = $next->{value};
			my $t = $next->toScriptXml;
			if ($value->isList && ! $value->isBlock) {
				my $q = $value->{quote} ? "'" : "";
				$t =~ s/(^.*?)>\s*(.*)/$1>$q($2/;
				$t =~ s/(.*);(.*)/$1)$2/;
			}
			$s .= "$t ";
			$next = $next->{next};
		}
		$s =~ s/\s+$//;
		$s .= ";$etag";
		$s;
	}
package lambda::base;
	sub isBlock {}
	sub isCommandBlock {}
	sub isDefinitionBlock {}
package lambda::block;
	use vars ('@ISA');
	@ISA = qw (lambda::list);
	sub new {
		my $self = bless {}, shift;
		$self->{quote} = shift;
		my %p = ();
		$self->{properties} = \%p;
		my @f = ();
		$self->{functions} = \@f;
		$self;
	}
	sub temp {
		my ($block, $property) = @_;
		my $symbol = lambda::symbol->new;
		$block->{properties}->{$symbol->{value}} = $property;
		$symbol;
	}
	sub eraseParameter {
		my $block = shift;
		my $id = $block->{id};
		$_->erase foreach @{$block->{functions}};
		delete $block->{functions};
		delete $block->{result};
		my $properties = $block->{properties};
		foreach (keys %{$properties}) {
			$properties->{$_}->erase ($id);
			delete $properties->{$_};
		}
		delete $block->{properties};
		delete $block->{verbose};
		$block;
	}
	sub copy {
		my ($block, $newProperties) = @_;
		my %ids = ();
		my $properties = $block->{properties};
		if ($newProperties && $properties) {
			while (my ($key, $property) = each %{$properties}) {
				my $id = $property->{id};
				$ids{$key} = $newProperties->{$id} = $property->copy ($newProperties);
			}
		}
		my $newBlock = lambda::list::listCopy ($block, $newProperties);
		my $functions = $block->{functions};
		my @newBlockFunctions = ();
		foreach (@{$block->{functions}}) {
			push @newBlockFunctions, $_->copy;
		}
		$newBlock->{functions} = \@newBlockFunctions;
		while (my ($key, $property) = each %ids) {
			$newBlock->{properties}->{$key} = $property;
		}
		%ids = ();
		$newBlock->{verbose} = $block->{verbose};
		$newBlock;
	}
	sub string {
		my $block = shift;
		my $vars = join (", ", sort keys %{$block->{properties}});
		$vars =~ s/;//g;
		my $l = $block->{quote} ? "'{" : "{";
		$l .= $vars . ": " if $vars;
		my $next = $block->{first};
		while ($next) {
			my $value = $next->{value};
			$l .= $value->string . " " if $value;
			$next = $next->{next};
		}
		$l =~ s/\s+$//;
		"$l}";
	}
	sub isBlock {1}
	sub isCommandList {}
	sub toScriptXml {
		my $list = shift;
		my $s = "<div class=\"block\">\n{";
		my $next = $list->{first};
		while ($next) {
			$s .= $next->toScriptXml;
			$next = $next->{next};
		}
		$s .= "}\n</div>";
	}
	sub toCommandBlock {
		my $block = bless shift, "lambda::commandBlock";
		delete $block->{quote};
		delete $block->{parameter};
		$block;
	}
	sub toDefinitionBlock {
		my $dBlock = bless shift, "lambda::dBlock";
		$dBlock->{quote} = 1;
		my $next = $dBlock->{first};
		while ($next) {
			delete $next->{root};
			$next = $next->{next};
		}
		$dBlock;
	}
package lambda::commandBlock;
	use vars ('@ISA');
	@ISA = qw (lambda::block);
	sub new {
		lambda::block->new->toCommandBlock (@_);
	}
	sub erase {
		shift->eraseParameter->eraseAllAtoms;
	}
	sub isCommandBlock {1}
package lambda::dBlock;
	use vars ('@ISA');
	@ISA = qw (lambda::block);
	sub new {
		bless lambda::block->new->toDefinitionBlock;
	}
	sub erase {
		my $thread = lambda::thread->new;
		$thread->setValue (shift->eraseParameter->toCommandBlock);
		$thread->erase;
	}
	sub isDefinitionBlock {1}
package lambda::natural;
	use constant basel => 9;
	use constant base => 10 ** basel;
	our $one = lambda::natural->new (1);
	sub new {
		my $self = bless {}, shift;
		my @z = @_ ? @_ : ();
		my $n = scalar @z;
		while ($n) {
			$z[--$n] == 0 ? pop @z : last;
		}
		$self->{z} = \@z;
		$self;
	}
	sub copy {
		lambda::natural->new (@{shift->{z}});
	}
	sub toNatural {
		my $self = shift;
		$self = lambda::natural->new (@{$self->{z}}) if ! $self->isNatural;
		$self;
	}
	sub stringToNatural {
		my $s = shift;
		my @z = ();
		while (1) {
			my $l = length ($s) - basel;
			my $z = ($l < 0 ? $s : substr ($s, $l, basel)) || 0;
			push @z, $z;
			return lambda::natural->new (@z) if $l <= 0;
			$s = substr ($s, 0, $l);
		}
	}
	sub valueToNatural {
		my $c = shift;
		my @z = ();
		while ($c) {
			push @z, ($c % lambda::natural::base);
			$c = int ($c / lambda::natural::base);
		}
		lambda::natural->new (@z);
	}
	sub toInteger {
		my $self = shift;
		$self = bless $self, "lambda::integer";
		$self->{sign} = shift || 0;
		$self;
	}
	sub ggt {
		my ($n1, $n2) = @_;
		my $ggt;
		while (1) {
			my $c = comp ($n1, $n2);
			if ($c == 0) {
				return $ggt ? $ggt->mult ($n1) : $n1;
			} elsif ($c == -1) {
				my $h = $n1;
				$n1 = $n2;
				$n2 = $h;
			}
			if ($n2->isZero) {
				return $ggt ? $ggt->mult ($n1) : $n1;
			} else {
				$ggt = lambda::natural->new (1) if ! $ggt;
			}
			return $ggt if $n2->isOne;
			if ($n1->isOdd) {
				if ($n2->isOdd) {
					$n1 = $n1->diff ($n2)->div2;
				} else {
					$n2 = $n2->div2;
				}
			} else {
				$n1 = $n1->div2;
				if (! $n2->isOdd) {
					$n2 = $n2->div2;
					$ggt = $ggt->mult2;
				}
			}
		}
	}
	sub comp {
		my ($i1, $i2) = @_;
		my @z1 = @{$i1->{z}};
		my @z2 = @{$i2->{z}};
		my $n1 = scalar @z1;
		my $n2 = scalar @z2;
		return 1 if $n1 > $n2;
		return -1 if $n1 < $n2;
		while ($n1) {
			--$n1;
			my $c = $z1[$n1] <=> $z2[$n1];
			return 1 if $c > 0;
			return -1 if $c < 0;
		}
		0;
	}
	sub le {
		my ($i1, $i2) = @_;
		$i2->comp ($i1) != -1 ? 1 : 0;
	}
	sub lt {
		my ($i1, $i2) = @_;
		$i2->comp ($i1) == 1 ? 1 : 0;
	}
	sub isZero {
		scalar @{shift->{z}} ? 0 : 1;
	}
	sub isOne {
		my $self = shift;
		my @z = @{$self->{z}};
		scalar @z == 1 && $z[0] == 1;
	}
	sub isOdd {
		@{shift->{z}}[0] & 1;
	}
	sub diff {
		my ($i1, $i2) = @_;
		my @z1 = @{$i1->{z}};
		my @z2 = @{$i2->{z}};
		my @z = ();
		my $n1 = scalar @z1;
		if ($n1) {
			my $n2 = scalar @z2;
			my $u = my $k = 0;
			do {
				my $d = $z1[$k] - $u;
				$d -= $z2[$k] if $k < $n2;
				$u = 0;
				if ($d < 0) {
					$d += lambda::natural::base;
					$u = 1;
				}
				push @z, $d;
			} until ++$k == $n1;
		}
		lambda::natural->new (@z);
	}
	sub add {
		my ($i1, $i2) = @_;
		my @z1 = @{$i1->{z}};
		my @z2 = @{$i2->{z}};
		my @z = ();
		my $n1 = scalar @z1;
		my $n2 = scalar @z2;
		my $n = $n1 < $n2 ? $n2 : $n1;
		my $u = my $k = 0;
		do {
			my $d = $u;
			$d += $z1[$k] if $k < $n1;
			$d += $z2[$k] if $k < $n2;
			$u = 0;
			if ($d >= lambda::natural::base) {
				$d -= lambda::natural::base;
				$u = 1;
			}
			push @z, $d;
		} until $k++ == $n;
		push @z, 1 if $u;
		lambda::natural->new (@z);
	}
	sub addA {
		my ($x, $a) = @_;
		my @z = @{$x->{z}};
		my $n = scalar @z;
		my $u = my $k = 0;
		do {
			my $d = $u + $a;
			$d += $z[$k];
			$u = 0;
			if ($d >= lambda::natural::base) {
				$d -= lambda::natural::base;
				$u = 1;
			}
			$z[$k] = $d;
		} until $k++ == $n;
		push @z, 1 if $u;
		$x;
	}
	sub mult2 {
		my @z1 = @{shift->{z}};
		my @z = ();
		my $k = scalar @z1;
		my $u = my $p = 0;
		do {
			my $z = $z1[$p];
			$z = ($z << 1) + $u;
			if ($z >= lambda::natural::base) {
				$u = 1;
				$z -= lambda::natural::base;
			} else {
				$u = 0;
			}
			push @z, $z;
		} until ++$p == $k;
		push @z, 1 if $u;
		lambda::natural->new (@z);
	}
	sub div2 {
		my @z1 = @{shift->{z}};
		my @z = ();
		my $k = scalar @z1;
		my $u = 0;
		while (--$k >= 0) {
			my $z = $u ? $z1[$k] + lambda::natural::base : $z1[$k];
			$u = $z & 1;
			unshift @z, ($z >> 1);
		}
		lambda::natural->new (@z);
	}
	sub mult {
		my ($x, $y) = @_;
		my @x = @{$x->{z}};
		my @y = @{$y->{z}};
		my $nx = scalar @x;
		my $ny = scalar @y;
		return lambda::natural->new if ! $nx || ! $ny;
		my $n = $nx < $ny ? $ny : $nx;
		if ($n > 1) {
			$n = ++$n >> 1;
			if ($nx <= $n) {
				my $y1 = lambda::natural->new (splice (@y, 0, $n));
				my $y2 = lambda::natural->new (@y);
				return karazuba ($n, $y1, $y2, $x);
			} elsif ($ny <= $n) {
				my $x1 = lambda::natural->new (splice (@x, 0, $n));
				my $x2 = lambda::natural->new (@x);
				return karazuba ($n, $x1, $x2, $y);
			}
			my $x1 = lambda::natural->new (splice (@x, 0, $n));
			my $y1 = lambda::natural->new (splice (@y, 0, $n));
			my $x2 = lambda::natural->new (@x);
			my $y2 = lambda::natural->new (@y);
			return karazuba ($n, $x1, $x2, $y1, $y2);
		}
		my $a = $x[0] * $y[0];
		my $b = int ($a / lambda::natural::base);
		$a = $a % lambda::natural::base;
		lambda::natural->new ($a, $b);
	}
	sub karazuba {
		my ($n, $x2, $x1, $y2, $y1) = @_;
		my @b = pot ($n);
		my $p2 = $x2->mult ($y2);
		return lambda::natural->new (@b, @{$x1->mult ($y2)->{z}})->add ($p2) if ! $y1;
		my $p1 = $x1->mult ($y1);
		my $p3 = ($x1->add ($x2))->mult ($y1->add ($y2))->diff ($p1->add ($p2));
		lambda::natural->new (@b, @b, @{$p1->{z}})->add (lambda::natural->new (@b, @{$p3->{z}}))->add ($p2);
	}
	sub pot {
		my $n = shift;
		my @b = ();
		my @b0 = (0);
		while (1) {
			if ($n % 2) {@b = (@b, @b0); --$n}
			return @b if ! $n;
			@b0 = (@b0, @b0);
			$n = $n >> 1;
		}
	}
	sub div {
		my ($x, $y) = @_;
		my @x = @{$x->{z}};
		my @y = @{$y->{z}};
		my $nx = scalar @{$x->{z}};
		my $ny = scalar @{$y->{z}};
		return lambda::error->new (18) if $ny == 0;
		return (lambda::natural->new, lambda::natural->new) if $nx == 0;
		my $n = $nx - $ny;
		return (lambda::natural->new, $x->copy) if $n < 0;
		my $sx = $nx == 1 ? $x[0] : lambda::natural::base * $x[$nx - 1] + $x[$nx - 2];
		my $sy = $y[$ny - 1];
		if ($n) {
			--$n;
		} elsif ($nx > 1) {
			$sy *= lambda::natural::base;
		}
		my $q = lambda::natural->new (pot ($n), @{valueToNatural (int ($sx / $sy + 0.5))->{z}});
		while (1) {
			my $xx = $q->mult ($y);
			if ($xx->le ($x)) {
				my $r = $x->diff ($xx);
				return ($q, $r) if $r->lt ($y);
				$q = $q->add ($r->div ($y));
			} else {
				my $r = $xx->diff ($x);
				$q = $q->diff ($r->div ($y));
				$q = $q->diff ($one);
			}
		}
	}
	sub string {
		my $s = "";
		$s .= sprintf ("%0.*d", basel, $_) foreach reverse @{shift->{z}};
		$s =~ s/^0+//;
		$s ? $s : "0";
	}
	sub isNatural {1};
package lambda::integer;
	use vars ('@ISA');
	@ISA = qw (lambda::natural);
	sub new {
		my $name = shift;
		my $sign = shift || 0;
		my $self = bless lambda::natural->new (@_), $name;
		$self->{sign} = $sign;
		$self;
	}
	sub copy {
		my $self = shift;
		lambda::integer->new ($self->{sign}, @{$self->{z}});
	}
	sub stringToInteger {
		my ($name, $s) = @_;
		my $sign = 0;
		if ($s =~ s/^([+-])//) {
			$sign = 1 if $1 eq "-";
		}
		lambda::natural::stringToNatural ($s)->toInteger($sign);
	}
	sub mult {
		my ($x, $y) = @_;
		lambda::natural::mult ($x->toNatural, $y->toNatural)->toInteger ($x->{sign} == ($y->{sign} || 0) ? 0 : 1);
	}
	sub div {
		my ($x, $y) = @_;
		my $sx = $x->{sign};
		my ($z, $r) = $x->toNatural->div ($y);
		if ($r->isZero || $sx == 0) {
			($z->toInteger ($sx), $r);
		} else {
			($z->add (lambda::natural::valueToNatural ("1"))->toInteger->switchSign, $y->diff ($r));
		}
	}
	sub switchSign {
		my $self = shift;
		return $self if $self->isZero;
		$self->{sign} = $self->{sign} ? 0 : 1;
		$self;
	}
	sub subA {
		my ($x, $a) = @_;
		return $x->addA ($a) if $x->{sign};
		my @z = @{$x->{z}};
		my $n = scalar @z;
		my $d = my $u = my $k = 0;
		do {
			$d = $z[$k] - $u - $a;
			$u = 0;
			if ($d < 0) {
				$d += lambda::natural::base;
				$u = 1;
			}
			@{$x->{z}} = $d;
		} until ++$k == $n;
		if ($u) {
			shift @{$x->{z}}, 1;
		} elsif (! $d) {
			pop @{$x->{z}};
		}
		$x;
	}
	sub add {
		my ($x, $y) = @_;
		my $sx = $x->{sign};
		return $y->toInteger ($y->{sign}) if ! defined $x->{sign};
		my $sy = $y->{sign} || 0;
		if ($sx == $sy) {
			return lambda::natural::add ($x, $y)->toInteger ($sx);
		} else {
			my $c = $x->lambda::natural::comp ($y);
			if ($c == 0) {
				return lambda::natural->new ();
			} elsif ($c == -1) {
				return lambda::natural::diff ($y, $x)->toInteger ($sy);
			} else {
				return lambda::natural::diff ($x, $y)->toInteger ($sx);
			}
		}
	}
	sub diff {
		my ($a, $b) = @_;
		my $sign = $b->{sign};
		my $result = add ($a, switchSign ($b));
		$b->{sign} = $sign;
		$result;
	}
	sub string {
		my $self = shift;
		my $s = lambda::natural::string ($self);
		$self->{sign} ? "-$s" : $s;
	}
	sub isNatural {};
package lambda::base;
	sub isFunction {}
package lambda::function;
	use vars ('@ISA');
	@ISA = qw (lambda::base);
	sub new {
		my $self = bless {}, shift;
		my ($atom, $sub, $return, @signatur) = @_;
		$self->{return} = $return;
		$self->{signatur} = \@signatur;
		my %devs = ();
		my $devs = $self->{devices} = \%devs;
		if (ref $sub eq "lambda::dBlock") {
			$self->{code} = $sub->toDefinitionBlock;
			$self->{parameter} = $sub->{parameter};
			lambda::addInFunktionalProperties ($devs, $sub, 1);
		} else {
			$self->{sub} = $sub;
			$self->{init} = lambda::init->can ($sub);
			$self->{command} = lambda::command->can ($sub);
		}
		my $search = "^";
		my $i = 0;
		my $s = my $spaceNext = "";
		foreach (@signatur) {
			my $space = " ";
			if ($_ =~ s/^\(//) {
				$self->{loop} = $i;
				$search .= "("
			}
			++$i;
			$_ =~ /([^)]*)\)?/;
			my $symbol = $1;
			$symbol =~ s/#$//;
			if ($symbol eq "\@*") {
				$s = ".*";
			} elsif ($symbol =~ /(.+)\@symbol$/) {
				$s = "([^' ]+|'[^ ]*'$1'[^ ]*')";
			} elsif ($symbol eq "\@symbol") {
				$s = "[^' ]+";
			} elsif ($symbol eq "\@value") {
				$s = "([^ ']+|'[^ ]*'value'[^ ]*')";
			} elsif ($symbol eq "\@data") {
				$s = "([^ ']+|'[^ ]*'data'[^ ]*')";
			} elsif ($symbol eq "data") {
				$s = "''data'[^ ]*''";
			} elsif ($symbol eq "\@list") {
				$s = "'list";
			} elsif ($symbol eq "\@block") {
				$s = "'block";
			} elsif ($symbol =~ /^#(.*)/) {
				$s = "''data'class('[^ ]+|.{0})'$1'[^ ]*'";
			} elsif ($symbol eq "class") {
				$s = "''data'class'[^ ]*''";
			} elsif ($symbol =~ /^'(.*)/) {
				$s = "$1";
			} elsif ($atom->findClass ($symbol)->isUndefined) {
				if ($sub eq "value_formula") {
					my $a;
				}
				undef $lambda::error;
				$symbol =~ s/([\(\)\{\}\[\]\\\|\/\+\?\*\.\^\&\-])/\\$1/g;
				if ($symbol =~ /@/) {
					$symbol .= "@";
					$symbol =~ s/(.+?)@/\($1 \)\|/g;
					$symbol =~ m/\@$/ ? $symbol =~ s/\@$/\.\{0\}/ : $symbol =~ s/\|$//;
					$s = "($symbol)";
					$space = "";
				} else {
					$s = "$symbol";
				}
			} else {
				$s = "'[^ ]*'$symbol'[^ ]*'";
			}
			$search .= ($i == 1) ? $s : "$spaceNext$s";
			$spaceNext = $space;
			$search .= ")*" if $_ =~ s/\)$//;
		}
		$self->{search} = "$search\$";
		$self;
	}
	sub copy {
		my $self = shift;
		my $new = bless {}, ref $self;
		$new->{search} = $self->{search};
		$new->{signatur} = $self->{signatur};
		$new->{code} = $self->{code}->copy if $self->{code};
		$new->{call} = $self->{call};
		$new->{devices} = $self->{devices};
		$new->{loop} = $self->{loop};
		$new->{init} = $self->{init};
		$new->{command} = $self->{command};
		$new->{sub} = $self->{sub};
		$new;
	}
	sub init {
		my ($function, $atom) = @_;
		if ($lambda::debug && $lambda::debug =~ /C/i || 4 <= main::AttrVal ($atom->lambda->{hash}->{NAME}, "verbose", 0)) {
			main::Log3 (undef, 0, $atom->{value}->string . " init::" . $function->string);
		}
		$atom->{value}->{function} = $function;
		return $atom->{return} = $function->{return}->copy if $function->{code} || ! (my $init = $function->{init});
		my $list = $atom->setPointer;
		my $return = $init->($atom) || $lambda::undefined;
		return if $lambda::error;
		return $return if $return->isEmpty;
		my $newAtom = $list->current;
		return $lambda::undefined if ! $newAtom;
		$atom->{id} && $newAtom->{id} == $atom->{id} ? return ($atom->{return} = $return): $newAtom->analyze;
	}
	sub call {
		my ($function, $atom, @values) = @_;
		if ($lambda::debug && $lambda::debug =~ /E/i || 5 <= main::AttrVal ($atom->lambda->{hash}->{NAME}, "verbose", 0)) {
			main::Log3 (undef, 0, $atom->{value}->string . " comm::" . $atom->lambda->string);
			main::Log3 (undef, 0, $atom->{value}->string . " comm::" . $function->string);
		}
		my @sig = @{$function->{signatur}};
		my $n = scalar @sig;
		my $l = $function->{loop};
		my $i = 0;
		foreach (@values) {
			my $s = $sig [$i++];
			last if $s eq "\@*";
			return lambda::error->new (78, $i, $function, $atom->{value}) if $_->isEmpty && $s =~ m/#$/;
			$i = $l if $l && $i == $n;
		}
		my $call = $function->{command};
		return (\&$call)->($atom, @values) || $lambda::undefined if $call;
		my $block = $function->{code};
		my $properties = $block->{properties};
		my %oldProperties = ();
		my %newProperties = ();
		my $new = $atom->newAtomAfter;
		my $next = $atom->first;
		foreach (@{$block->{parameter}}) {
			if ($_) {
				my $oldProperty =  $properties->{$_};
				$oldProperties{$_} = $oldProperty;
				$newProperties{$oldProperty->{id}} = $next->{return};
				delete $properties->{$_};
			}
			$next = $next->{next};
		}
		$new->setValue ($block->copy (\%newProperties)->toCommandBlock, $atom->{return});
		$atom->erase;
		$block->{properties}->{$_} = $oldProperties{$_} foreach keys %oldProperties;
		$new->{value};
	}
	sub erase {
		if (my $code = shift->{code}) {
			delete $code->{par};
			$code->erase;
		}
	}
	sub string {
		my $self = shift;
		my $para = $self->{search};
		$para =~ s/^\^|\$$|\[\^ \]\*'//g;
		$para =~ s/\\([^ ])/$1/g;
		my $s = " --> ";
		$s .= $self->{code} ? $self->{code}->string : $self->{sub};
	}
	sub isFunction {1}
package lambda::base;
	sub isFunctional {}
package lambda::functional;
	use vars ('@ISA');
	@ISA = qw (lambda::list);
	sub isFunctional {1}
	sub isCommandList {}
	sub toCommandList {bless shift, "lambda::list"}
package lambda;
	push (@lambda::master::functions, qw (
		data_value . data
		data_log . log,@*
		data_log1 . log,string@symbol
		data_debug . debug,number,string;
		data_out . out
		data_toBoolean boolean data,toBoolean
		data_system boolean system,data,(data)
		data_toString string data,toString
		data_above . data,above
	));
	$lambda::error::msgE{"data_01"} = "Die Eigenschaft &&1 ist in &&2 nicht definiert.";
	$lambda::error::msgE{"data_02"} = "Die Klasse &&1 ist kein Nachfahre von &&2.";
	$lambda::error::msgE{"data_03"} = "Im übergeordneten Block ist das Symbol &&1 nicht definiert.";
package lambda::base;
	sub isData {}
package lambda::data;
	use vars ('@ISA');
	@ISA = qw (lambda::base);
	sub new {
		my $self = bless {}, shift;
		($self->{class}, $self->{value}) = @_;
		$self;
	}
	sub allKeys {
		my $self = shift;
		my %keys = ();
		while ($self) {
			$keys{$_} = 1 foreach keys %{$self->{properties}};
			$self = $self->{class};
		}
		keys %keys;
	}
	sub isASister {
		my ($data, $dataOld) = @_;
		if ($dataOld->isClsClass) {
			return lambda::error->new ("class_03", $dataOld, $data) if ! $dataOld->IsASubclass ($data);
		} else {
			my $oldClass = $dataOld->{class};
			my $class = $data->{class};
			return lambda::error->new ("class_03", $oldClass, $class) if ! $oldClass->isASubclass ($class);
		}
		my @keys = $dataOld->allKeys;
		foreach (@keys) {
			my $new = $data->property ($_);
			return lambda::error->new ("data_01", $_, $data->string) if $new->isUndefined;
			$new->{value}->isASister ($dataOld->property ($_)->{value});
			return if $lambda::error;
		}
		$lambda::undefined;
	}
	sub copy {
		my $self = shift;
		return $self if $self->isEmpty;
		my $new = bless {}, ref $self;
		foreach (keys %{$self}) {
			$new->{$_} = $self->{$_} if $_ !~ /properties/i;
		}
		my $properties = $self->{properties};
		foreach (keys %{$properties}) {
			$new->{properties}->{$_} = $properties->{$_}->copy;
		}
		$new;
	}
	sub compare {
 		my ($o1, $o2) = @_;
		return 0 if $o1 eq $o2;
		my $c1 = $o1->{class};
		my $c2 = $o2->{class};
		return 1 if $c1->compare ($c2);
		my %keys;
		$keys {$_} = 1 for allKeys ($o1);
		$keys {$_} ? $keys {$_} = 0 : return -1 for allKeys ($o2);
		foreach (keys %keys) {
			return -1 if $keys {$_};
			return 1 if $o1->property ($_)->compare ($o2->property ($_));
		}
		return 0;
	}
	sub includedDevices {
		my $data = shift;
		my $device = $data->{device};
		return ($device->{value}) if $device;
		my $properties = $data->{properties};
		my @devices = ();
		return @devices if ! $properties;
		@devices = (@devices, $properties->{$_}->{value}->includedDevices) foreach keys %{$properties};
		@devices;
	}
	sub property {
		my ($self, $name) = @_;
		my $emptyProperty;
		while ($self) {
			my $properties = $self->{properties};
			if ($properties) {
				my $property = $properties->{$name};
				if ($property) {
					return $property if ! $property->{value}->isEmpty;
					$emptyProperty = $property if ! $emptyProperty;
				}
			}
			$self = $self->{class};
		}
		$emptyProperty ? $emptyProperty : $lambda::undefined;
	}
	sub modifyProperty {
		my ($self, $name, $value) = @_;
		my $property = $self->{properties}->{$name};
		if (! $property) {
			$property = $self->{class}->property ($name);
			if ($property->isUndefined) {
				$property = lambda::property->new ($value->{class}, $value);
				return $self->{properties}->{$name} = $property if $value->isClass;
			} else {
				$property = $property->copy;
			}
		}
		$self->{properties}->{$name} = $property;
		return $property->changeValue ($value) if ! $value->isClass;
		$property->{value} = $value;
		$property;
	}
	sub erase {
		my $data = shift;
		delete $data->{class};
		my $properties = $data->{properties};
		foreach (keys %{$properties}) {
			$properties->{$_}->erase;
			delete $properties->{$_};
		}
		delete $data->{properties};
	}
	sub isData {1}
package lambda::init;
	sub _data_makeString {
		use constant toString => lambda::symbol->new ("toString", 1);
		my $atom = shift;
		my $list = $atom->{value};
		$list->first;
		while (my $next = $list->current) {
			my $value = $next->{value};
			my $return = $next->{return};
			if ($return->isSymbol) {
				delete $next->{return};
				$next->setValue ($return->toWord);
			} elsif ($return->{class}->isASubclass ($lambda::master::string)) {
			} else {
				$next->newAtomAfter->appendAtoms ($next, toString)->analyzeCommandList;
			}
			$list->next;
		}
		$atom->analyzeCommandList;
	}
	sub data_getProperty {
		my ($data, $symbol) = shift->firsts (2);
		my $property = $data->{return}->{value}->property ($symbol->{value}->{value});
		$property->isUndefined ? $property : lambda::property->new ($property->{class});
	}
	sub data_value {
		shift->first->{return};
	}
	sub data_out {
		data_log (@_);
	}
	sub data_log {
		my $atom = shift;
		my ($first, $second) = $atom->firsts (2);
		$atom = $atom->newAtomAfter->appendAtoms ($first, $atom);
		_data_makeString ($atom->second);
		$atom->analyzeCommandList;
	}
	sub data_system {
		data_log (@_);
	}
	sub data_above {
		my $atom = shift;
		my $symbol = $atom->first->{value};
		return lambda::error->new (2, $symbol) if ! $symbol->isSymbol;
		my $return = $atom->block->{root}->findSymbol ($symbol);
		return lambda::error->new ("data_03", $symbol) if $return->isUndefined;
		$atom->{return} = $return;
	}
package lambda::command;
	sub data_getProperty {
		my ($atom, $self, $symbol) = @_;
		$self->refresh ($atom);
		return $lambda::error if $lambda::error;
		my $name = $symbol->{value};
		my $property;
		if ($self->isEmpty) {
			$property = lambda::property->new ($self->{class}->property ($name)->{class});
		} else {
			$property = $self->{properties}->{$name};
			if (! $property) {
				$property = $self->property ($name);
				$property = $self->{properties}->{$name} = $property->copy
			}
		}
		$atom->{return} = $property;
		my $value = $property->{value};
		$value->{device} = $self->isDevice ? $self : $self->{device};
		$value;
	}
	sub data_value {
		shift->{value}->{first}->{return}->{value};
	}
	sub data_toBoolean {
		shift;
		my $value = shift;
		my $class = $value->{class};
		if ($value->isEmpty) {
		} elsif ($class->isASubclass ($lambda::master::boolean)) {
			return $lambda::true if $value->{value};
		} elsif ($class->isASubclass ($lambda::master::number)) {
			return $lambda::true if $value->{num};
		} elsif ($class->isASubclass ($lambda::master::string)) {
			return $lambda::true if $value->{value} !~ /^.{0}$|^false$/i;
		}
		$lambda::false;
	}
	sub data_out {
		data_log (@_);
	}
	sub data_debug {
		my ($atom, $op, $number, $string) = @_;
		my $block = $atom->block;
		my $verbose = $block->{value}->{verbose};
		while (! $verbose) {
			$block = $block->{root}->block;
			last if $block->isMaster;
			$verbose = $block->{value}->{verbose};
		}
		main::Log3 (undef, 0, $atom->lambda->string ."\n" . $string->{value}) if $verbose && $number->string <= $verbose;
		$lambda::undefined;
	}
	sub data_log1 {
		my $string = $_[2];
		main::Log3 (undef, 0, $string->isEmpty ? $string->string : $string->{value});
		$lambda::undefined;
	}
	sub data_system {
		system ($_[2]->{value}) ? $lambda::false : $lambda::true;
	}
	sub data_toString {
		$lambda::master::string->new ($_[1]->string);
	}
	sub data_above {
		shift->{return}->{value};
	}
package lambda::base;
	sub isProperty {}
package lambda::property;
	use vars ('@ISA');
	@ISA = qw (lambda::base);
	sub new {
		my $property = bless {}, shift;
		$property->{id} = $property->id;
		my ($class, $value) = @_;
		if ($value) {
		} elsif ($class->isClass) {
			$value = lambda::empty->new ($class);
		} else {
			$value = $class;
			$class = $value->{class};
		}
		$property->{class} = $class;
		$property->{value} = $value;
		$property;
	}
	sub erase {
		my $self = shift;
		return if $self->{readOnly};
		delete $self->{value};
		delete $self->{class};
		delete $self->{inArray};
		delete $self->{changed};
		delete $self->{readOnly};
		delete $self->{copyProtected};
	}
	sub copy {
		my $property = shift;
		return $property if $property->{copyProtected};
		my $newProperty = lambda::property->new ($property->{class}, $property->{value});
		$newProperty->{readOnly} = $newProperty->{readOnly};
		$newProperty;
	}
	sub changeValue {
		my ($property, $newValue, $atom) = @_;
		if ($newValue->compare ($property->{value})) {
			$property->{value} = $newValue;
			$property->{changed} = 1;
			if ($atom && ! $newValue->isClass) {
				my $thread = $atom->isMaster ? $atom : ($newValue->includedDevices ? $lambda::master : $atom->lambda);
				$thread->putChangedProperty ($property);
			}
		} else {
			delete $property->{changed};
		}
		$property;
	}
	sub compare {
		my ($p1, $p2) = @_;
		return 0 if $p1 eq $p2;
		my $e1 = $p1->{class}->isEmpty;
		my $e2 = $p2->{class}->isEmpty;
		return 1 if ($e1 && ! $e2) || (! $e1 && $e2);
		return $p1->{value} eq $p2->{value} ? 0 : 1 if $e1;
		return 1 if $p1->{class}->compare ($p2->{class});
		$p1->{value}->compare ($p2->{value});
	}
	sub dependOn {
		my ($waitProperty, $changedProperty) = @_;
		return 1 if $waitProperty eq $changedProperty;
		my $properties = $waitProperty->{value}->{properties};
		if ($properties) {
			foreach (values %{$properties}) {
				return 1 if $_->dependOn ($changedProperty);
			}
		}
		if (my $arrayProperty = $changedProperty->{inArray}) {
			return 1 if $waitProperty->dependOn ($arrayProperty);
		}
		if (my $dev = $changedProperty->{value}->{device}) {
			return 1 if $waitProperty->{class}->isASubclass ($lambda::master::fhemDevice) && $dev eq $waitProperty->{value};
		}
		undef;
	}
	sub isProperty {1}
	sub string {
		my $self = shift;
		my $s = $self->{class}->string . ":" . $self->{value}->string;
		$self->{readOnly} ? "/^$s/" : "/$s/";
	}
package lambda::await;
	use vars ('@ISA');
	@ISA = qw (lambda::base);
	sub new {
		my $self = bless {}, shift;
		$self->initialize;
	}
	sub initialize {
		my $self = shift;
		my @p = ();
		$self->{waitPoints} = \@p;
		my @d = ();
		$self->{devices} = \@d;
		delete $self->{time};
		$self->{index} = -1;
		$self;
	}
package lambda::waitPoint;
	use vars ('@ISA');
	@ISA = qw (lambda::base);
	sub new {
		my $self = bless {}, shift;
		$self->{value} = shift;
		$self->{index} = shift;
		$self;
	}
package lambda;
	push (@lambda::master::functions, qw (
		class_eq boolean class,=,class;class,!=,class
	));
	push (@lambda::master::functions1, qw (
		class_modClassProperty . class,@symbol,value
		class_modClass . class,@symbol,data,(@symbol,data);class,(@symbol,data),@block;class,(@symbol,data),@block,@block
		class_newClass . @symbol,:=,class,(@symbol,data);@symbol,:=,class,(@symbol,data),@block
	));
	$lambda::error::msgE{"class_01"} = "Symbol &&1 ist in diesem Block bereits definiert.";
	$lambda::error::msgE{"class_02"} = "Initialisierungs- oder Finishblock hier nicht zulässig. &&1";
	$lambda::error::msgE{"class_03"} = "&&1 ist keine von &&2 abgeleitete Klasse.";
	$lambda::error::msgE{"class_04"} = "Modifizierung der Klasse hier nicht möglich.";
package lambda::base;
	sub isClsClass {}
	sub isClass {}
package lambda::clsClass;
	use vars ('@ISA');
	@ISA = qw (lambda::data);
	my $loner;
	sub new {$loner ? $loner : $loner = newClass (undef, "class")}
	sub newClass {
		my ($parent, $name) = @_;
		my $class = lambda::data::new ("lambda::cls" . ucfirst ($name), $parent);
		$class->{name} = $name;
		$class->{intern} = 1;
		my @init = ();
		$class->{init} = \@init;
		my @finish = ();
		$class->{finish} = \@finish;
		$class;
	}
	sub searchString {
		my $l = shift->qName;
		$l =~ s/^(class)|(".*)//g;
		$l =~ s/^'value//;
		" ''data'value$l'";
	}
sub erase {
		my $class = shift;
		$_->erase foreach @{$class->{init}};
		$_->erase foreach @{$class->{finish}};
		delete $class->{name};
		delete $class->{intern};
		delete $class->{class};
		delete $class->{init};
		delete $class->{finish};
	}
	sub isASubclass {
		my ($subClass, $class) = @_;
		return 1 if $class eq $subClass;
		return undef if ! $class->isClass;
		my $mask = $class->qName (1);
		$subClass->qName =~ m/^$mask/ ? 1 : undef;
	}
	sub ancestor {
		my ($class0, $class1) = @_;
		while (1) {
			return $lambda::undefined if ! $class0->isClass || ! $class1->isClass;
			return $class1 if $class0->isASubclass ($class1);
			return $class0 if $class1->isASubclass ($class0);
			$class0 = $class1->{class};
			$class1 = $class1->{class};
		}
	}
	sub qName {"class'"}
	sub string {"[class]"}
	sub init {}
	sub isClsClass {1}
package lambda::init;
	sub class_newClass {
		my $atom = shift;
		my ($first, $second, $third) = $atom->firsts (3);
		my $symbol = $first->{value};
		my $class = bless {}, "lambda::clsValue";
		my $className = $class->{name} = $symbol->{value};
		my $oldProperty = $third->{return};
		$class->{class} = $oldProperty->{value};
		my @init = ();
		$class->{init} = \@init;
		my @finish = ();
		$class->{finish} = \@finish;
		my $classProperty = $atom->defSymbol ($symbol, lambda::property->new ($lambda::master::class, $class));
		return if $lambda::error;
		my $oldClassName = $oldProperty->{value}->{name};
		if ($oldClassName eq lcfirst ($oldClassName)) {
			my $toClassName = "to" . ucfirst ($oldClassName);
			$atom->addFunction ("value_downgrade1", $oldProperty->copy, $className, $toClassName);
		}
		$second->erase;
		$third->erase;
		if ($atom->second) {
			$first->{return} = $classProperty;
			$atom->fixAnalyze ("class_modClass");
			return if $lambda::error;
			return $classProperty;
		}
		$atom->erase;
		return $lambda::undefined;
	}
	sub class_modClass {
		my $atom = shift;
		my $classAtom = $atom->first;
		my $classProperty = $classAtom->{return};
		my $class = $classProperty->{value};
		my $className = $class->{name};
		return lambda::error->new ("class_04", $atom->{value}) if ! $atom->block->{value}->{properties}->{$className};
		my $second = $atom->second;
		while ($second) {
			my $symbol = $second->{value};
			last if $symbol->isBlock;
			my $name = $second->{value}->{value};
			my $third = $second->{next};
			my $next = $third->{next};
			my $oldProperty = $class->property ($name);
			if ($oldProperty->isUndefined) {
				$oldProperty = $atom->defProperty ($class, $name, $class->{properties}->{$name} = $third->{return}->copy);
			} else {
				my $oldValue = $oldProperty->{value};
				if ($oldValue->isClass) {
					my $newValue = $third->{return}->{value};
					return lambda::error->new (60, $newValue, $oldValue) if ! $oldValue->isASubclass ($newValue);
					$class->{properties}->{$name} = $newValue;
				}
			}
			if ($oldProperty->{value}->isClass) {
				$second->erase;
				$third->erase;
				$atom->fixAnalyze ("data_value");
			} elsif ($third->{next}) {
				$third->newAtomAfter->appendAtoms ($atom->first, $second, $third)->fixAnalyze ("class_modClassProperty");
				return if $lambda::error;
			} else {
				$atom->fixAnalyze ("class_modClassProperty");
				return if $lambda::error;
			}
			$second = $next;
		}
		if ($second) {
			my $third = $second->{next};
			my $block = $second->{value}->toCommandBlock;
			$block->{properties}->{my} = $classProperty;
			$second->analyze;
			return if $lambda::error;
			my @init = @{$class->{init}};
			push @init, $second->detach;
			$class->{init} = \@init;
			if ($third) {
				$block = $third->{value}->toCommandBlock;
				$block->{properties}->{my} = $classProperty;
				$$third->analyze;
				return if $lambda::error;
				my @finish = @{$class->{finish}};
				unshift @finish, $third->detach;
				$class->{finish} = \@finish
			}
		}
		$atom->erase if ! $atom->first;
		$classProperty;
	}
	sub class_eq {
		my $atom = shift;
		my ($c1, $op, $c2) = $atom->firsts (3);
		my $v = $c1->{return}->{value}->qName eq $c2->{return}->{value}->qName ? $lambda::true : $lambda::false;
		$v->{value} = ! $v->{value} if $op->{value}->{value} eq "!=";
		$atom->{return} = lambda::property->new ($v);
	}
package lambda::command;
	sub class_modClass {$_[1]}
	sub class_modClassProperty {
		my ($atom, $class, $symbol, $value) = @_;
		$class->{properties}->{$symbol->{value}}->changeValue ($value->copy);
		$class;
	}
	sub class_eq {shift->{return}->{value}};
no warnings 'uninitialized';
package lambda;
	push (@lambda::master::functions, qw (
		value_isA boolean value,isA,class
		value_isEmpty boolean value,isEmpty
		value_isNotEmpty boolean value,isNotEmpty
		value_new1 . new,class,@symbol,data,(@symbol,data);new,class,value,(@symbol,data)
		value_new2 . new,value,class,(@symbol,data)
		value_new . new,class
		value_empty . empty,class;class,empty
		value_evaluate . value,evaluate
		value_minus . value,-,value
		value_div . value,/,value
		value_eq boolean value,=,value
		value_ne boolean value,!=,value
		value_Lt boolean value#,<,value#
		value_Gt boolean value#,>,value#
		value_Ge boolean value#,=>,value#
		value_NE boolean value#,<>,value#
		value_EQ boolean value#,<=>,value#
		value_minmax . min@max,value,value,(value)
		value_ifValue . if,value,value,value,(value,value),value;if,value,@symbol,value,value,(value,value),value
		value_ifBlock . if,value,value,@block,(value,@block);if,value,value,@block,(value,@block),@block
		value_type class value,type
		value_forEach . forEach,value@symbol,value,value,value,@block
		value_isClass boolean value,is,class
		value_defVar . @symbol,:=,@*
		value_changeValue . value,:=,@*
		value_defRef . @symbol,==,value#;value,==,value#
		value_copyTo . value,copyTo,value
		value_downgrade . value,to,class
		value_downgrade1 . value,[to]
	));
	$lambda::error::msgE{"value_01"} = "&&1 ist vom Typ &&2. Die Klasse &&3 stammt nicht davon ab.";
	$lambda::error::msgE{"value_02"} = "Zuweisung des Symbols &&1 in &&2 nicht erlaubt!";
	$lambda::error::msgE{"value_03"} = "Eigenschaft &&1 in Klasse &&2 ist keine Eigenschaft in der Klasse &&3!";
	$lambda::error::msgE{"value_04"} = "Variable &&1 darf nicht mit seinem ersten Zeichen beginnen!";
	$lambda::error::msgE{"value_05"} = "Keine Operation zwischen &&1 und &&2 definiert!";
	$lambda::error::msgE{"value_06"} = "Operation nicht ausfürbar: &&1";
	$lambda::error::msgE{"value_07"} = "Operation mit einer Konstanten nicht zulässig.";
package lambda::base;
	sub isClsValue {};
	sub isValue {}
package lambda::clsValue;
	use vars ('@ISA');
	@ISA = qw (lambda::clsClass);
	sub new {lambda::classes::value->new (@_)}
	sub qName {
		use constant t => "'";
		use constant t0 => "[^\"]*";
		use constant t1 => "(\"" . t0 . "\")*";
		my ($self, $mask) = @_;
		my $name = $self->{name} . t;
		my $class = $self->{class};
		while (! $class->isClsClass) {
			$name = $class->{name} . t . "$name";
			$class = $class->{class}
		}
		$name = $lambda::master::class->{name} . t . "$name";
		$name = $name . t0 if $mask;
		foreach (sort $self->allKeys) {
			my $value = $self->property ($_)->{value};
			if ($value->isClass) {
				if ($mask) {
					$name .= t1;
					$name .= "\"" . $_ . "\\(" . $value->qName ($mask) . "\\)";
				} else {
					$name .= "\"" . $_ . "(" . $value->qName . ")";
				}
			}
		}
		$name = $name . t1 if $mask;
		$name =~ s/'([^']*')\1/'$1/g;
		$name;
	}
	sub string {
		my $self = shift;
		my $name = $self->{name};
		my $s = "";
		$s .= ",$_=" . $self->property ($_)->{value}->string foreach sort $self->allKeys;
		$s =~ s/^,//;
		$s ? "[$name:$s]" : "[$name]";
	}
	sub isClsValue {1};
	sub isClsClass {}
	sub isClass {1}
package lambda::classes::value;
	use vars ('@ISA');
	@ISA = qw (lambda::data);
	sub isValue {1}
	sub isConstant {shift->{constant}};
	sub new {
		my ($name, $class) = @_;
		my $self = bless $class->{class}->new, $name;
		$self->{class} = $class;
		$self;
	}
	sub string {
		my $self = shift;
		my $classIntern = my $class = $self->{class};
		my $s = my $t = "";
		if (! $class->isClsClass) {
			$classIntern = $classIntern->{class} while ! $classIntern->{intern};
			if ((my $name = $classIntern->{name}) ne "value") {
				my $call = "lambda::classes::$name"->can ("string");
				$t = " " . (\&$call)->($self);
			}
		}
		$s .= ";$_:" . $self->property ($_)->{value}->string foreach sort $self->allKeys;
		$s =~ s/^;//;
		my $name = $self->{value} ? $self->{value} : $class->{name};
		$s ? $t ? "{$name:$t|$s}" : "{$name|$s}" : $name;
	}
	sub compare {
		my ($v1, $v2) = @_;
		return 0 if $v1 eq $v2;
		return 1 if $v2->isEmpty || $v2->isList;
		my $c2 = $v2->{class};
		return 1 if $v1->{class}->qName ne $c2->qName;
		lambda::data::compare ($v1, $v2);
	}
	sub refresh {
		my ($self, $atom) = @_;
		my $root = $self;
		my @root = ();
		unshift @root, $root = $root->{class} while ! $root->{intern};
		$_->refresh ($self, $atom) foreach @root;
		$self;
	}
	sub copy {
		my ($from, $class) = @_;
		my $to = $class ? $class->new : $from->{class}->new;
		$from->copyTo ($to);
		my $properties = $from->{properties};
		$to->{constant} = $from->{constant}; #?
		$to->{properties}->{$_} = $properties->{$_}->copy foreach keys %{$properties};
		$to;
	}
	sub copyTo {
		my ($from, $to) = @_;
		my $class = $from->{class};
		return $to->{value} = $from->{value} if $class->{intern};
		$class = $class->{class} while ! $class->{intern};
		return if ((my $name = $class->{name}) eq "value");
		my $code = "lambda::classes::$name"->can ("copyTo");
		(\&$code)->($from, $to) if $code;
	}
	sub isDevice {shift->{class}->isASubclass ($lambda::master::device)}
	sub isA {shift->{class}->isASubclass (shift)}
	sub toScriptXml {"<span class=\"value\">" . shift->string . "<span />"}
package lambda::init;
	use constant pl => lambda::symbol->new ("+", 1);
	use constant mi => lambda::symbol->new ("-", 1);
	use constant mu => lambda::symbol->new ("*", 1);
	use constant in => lambda::symbol->new ("^-1", 1);
	sub value_empty {
		my $atom = shift;
		my ($first, $second) = $atom->firsts (2);
		my $f = $first->{return};
		my $c;
		if ($f->isSymbol) {
			$c = $second->{return}->{value};
			$second->erase;
		} else {
			$c = $f->{value};
			$first->erase;
			$first = $second;
		}
		my $p = lambda::property->new ($c);
		$first->{value} = $p->{value};
		$atom->fixAnalyze ("data_value", $p);
	}
	sub value_downgrade {
		my $atom = shift;
		my ($first, $op, $third) = $atom->firsts (3);
		my $valueClass = $first->{return}->{class};
		my $class = $third->{return}->{value};
		return lambda::error->new ("class_03", $valueClass, $class) if ! $valueClass->isASubclass ($class);
		lambda::property->new ($class);
	}
	sub value_isA {
		my $atom = shift;
		my ($value, $op, $class) = $atom->firsts (3);
		$atom->{return} = lambda::property->new ($value->{return}->{class}->isASubclass ($class->{return}->{value}) ? $lambda::true : $lambda::false);
	}
	sub value_defRef {
		my $atom = shift;
		my ($first, $op, $third) = $atom->firsts (3);
		my $symbol = $first->{return};
		my $property = $first->{return} = $third->{return}->copy;
		if ($symbol->isSymbol) {
			$atom->defSymbol ($symbol, $property);
			return if $lambda::error;
			$property->{pointer} = 1;
		} else {
			my $f = $symbol->{class};
			my $t = $property->{class};
			return lambda::error->new (7, $f, $t) if $f->qName ne $t->qName;
		}
		$lambda::undefined;
	}
	sub value_formula {
		use constant op => ("^", "* /", "+ -", "!~ ~", "> => <= < <=> <> != =", "& | and or");
		my $atom = shift;
		my ($a, $op, $b) = $atom->firsts (3);
		return lambda::error->new ("value_05", $atom->{value}) if $b && $op->{return}->isSymbol && ! $b->{next};
		if ($a->{return}->isSymbol) {
			$a = $op;
			$op = $b;
			$b = $b->{next};
		}
		while ($op) {
			$b = $op->{next};
			if ($op->{return}->isSymbol) {
				$a = $b;
				$op = $a->{next};
			} else {
				$b = $op;
				my $s1 = $a->{return}->{class}->searchString;
				my $s2 = $b->{return}->{class}->searchString;
				my $s = "$s1 *$s2";
				my $function = $atom->searchFunction ($s, "value_formula value_modify");
				if ($function->isUndefined) {
					$s = "$s1 +$s2";
					$function = $atom->searchFunction ($s, "value_formula value_modify");
					return lambda::error->new ("value_05", $a->{value}, $b->{value}) if $function->isUndefined;
					$op = lambda::symbol->new ("+", 1);
				} else {
					$op = lambda::symbol->new ("*", 1);
				}
				$a->newAtomAfter->setValue ($op, $op);
				$a = $b;
				$op = $a->{next};
			}
		}
		delete $atom->{return};
		foreach (op) {
			($a, $op, $b) = $atom->firsts (3);
			return $atom->fixAnalyze ("data_value") if ! defined $op;
			if ($a->{return}->isSymbol) {
				if ($a->{return}->isSymbol ($_)) {
					$a->newAtomAfter->appendAtoms ($a, $op)->analyzeCommandList;
					return $lambda::error if $lambda::error;
					($a, $op, $b) = $atom->firsts (3);
				} else {
					$a = $op;
					$op = $b;
					$b = $b->{next};
				}
			}
			while ($b) {
				my $next = $b->{next};
				return $atom->analyzeCommandList if ! $a->{before} && ! $next;
				if ($op->{return}->isSymbol ($_)) {
					$b->newAtomAfter->appendAtoms ($a, $op, $b)->analyzeCommandList;
					return $lambda::error if $lambda::error;
					last if ! $next;
				}
				$a = $next->{before};
				$op = $next;
				$b = $next->{next};
			}
		}
	}
	sub value_clone {
		my $atom = shift;
		my ($first, $second, $third) = $atom->firsts (3);
		my $return = $atom->first->{return};
		$return = $return->copy if ! $return->{value}->{constant};
		if ($third) {
			my $newClass = $third->{return}->{value};
			my $oldClass = $return->{class};
			return lambda::error->new ("class_03", $oldClass, $newClass) if ! $newClass->isASubclass ($oldClass);
			$return->{class} = $newClass;
		}
		$return;
	}
	sub value_defVar {
		my $atom = shift;
		my ($first, $second, $third) = $atom->firsts (3);
		my $symbol = $first->{value};
		if ($third->{next}) {
			$atom->newAtomAfter->appendAtoms ($first, $second, $atom);
			return $lambda::undefined;
		} elsif ($third->{value}->isBlock) {
			$third->{value}->toCommandBlock;
			$third->analyze;
			return if $lambda::error;
		}
		my $property = $third->{return};
		return lambda::error->new ("value_02", $property, $atom->{value}) if $property->isSymbol;
		$property = lambda::property->new ($property->{class});
		$first->{return} = $atom->defSymbol ($symbol, $property);
		return if $lambda::error;
		$atom->fixAnalyze ("value_changeValue", $lambda::undefined);
	}
	sub value_modify {
		my $atom = shift;
		my ($first, $next) = $atom->firsts (2);
		my $property = $first->{return};
		my $value = $property->{value};
		my $class = $property->{class};
		while ($next) {
			my $name = $next->{value}->{value};
			my $oldProperty = $value->property ($name);
			if ($oldProperty->isUndefined) {
				lambda::error->new (28, $name, $value);
				return $ambda_test::empty;
			}
			my $oldClass = $oldProperty->{class};
			$next = $next->{next};
			my $newProperty = $next->{return};
			my $newClass = $newProperty->{class};
			return lambda::error->new ("class_03", $newClass, $oldClass) if ! $newClass->isASubclass ($oldClass);
			if ($newProperty->{value}->isClass) {
				$class = $value->{class} = $property->{class} = $class->copy;
				$class->{properties}->{$name} = $newProperty;
				delete $value->{properties}->{$name};
			}
			$next = $next->{next};
		}
		$property;
	}
	sub value_evaluate {
		shift->first->{return}->copy;
	}
	sub value_minus {
		my $atom = shift;
		my ($a, $op, $b) = $atom->firsts (3);
		$b->newAtomAfter->appendAtoms ($op, $b);
		$b->newAtomAfter->appendAtoms ($b, "copy") if ! $b->containConstant;
		$a->newAtomAfter->setValue (pl, pl);
		$atom->analyzeCommandList;
	}
	sub value_div {
		my $atom = shift;
		my ($a, $op, $b) = $atom->firsts (3);
		$b->newAtomAfter->appendAtoms ($b, in);
		$b->newAtomAfter->appendAtoms ($b, "copy") if ! $b->containConstant;
		$op->setValue (mu, mu);
		$atom->analyzeCommandList;
	}
	sub value_eq {
		my $atom = shift;
		my $c1 = $atom->first->analyze->{class}->qName;
		my $c2 = $atom->third->analyze->{class}->qName;
		$c1 eq $c2 ||
			($c1 eq "class'value'string'word'" && $c2 eq "class'value'string'") ||
			($c2 eq "class'value'string'word'" && $c1 eq "class'value'string'") ?
			lambda::property->new ($lambda::master::boolean) : lambda::error->new (60, $c1, $c2);
	}
	sub value_ne {
		my $atom = shift;
		my ($first, $op, $third) = $atom->firsts (3);
		$op->{return} = $op->{value} = lambda::symbol->new ("=");
		my $list = $atom->{value};
		$atom->{value} = lambda::list->new;
		$atom->insertValues (lambda::symbol->new ("!"), $list);
		$atom->analyze;
	}
	sub value_EQ {
		my $atom = shift;
		my ($first, $op, $third) = $atom->firsts (3);
		my $new = $atom->newAtomAfter;
		$new->{value} = lambda::block->new;
		my $a = $new->setTemp ($first);
		my $b = $new->setTemp ($third);
		$new->appendValues (lambda::list->new);
		$new = $new->last;
		$new->insertValues (lambda::list->new, lambda::symbol->new ("&"), lambda::list->new);
		$new->first->insertValues ($a, lambda::symbol->new ("<="), $b);
		$new->last->insertValues ($b, lambda::symbol->new ("<="), $a);
		$atom->erase;
		$lambda::undefined;
	}
	sub value_NE {
		my $atom = shift;
		my $second = $atom->second;
		$second->{return} = $second->{value} = lambda::symbol->new ("<=>");
		my $new = $atom->newAtomAfter;
		$new->appendAtoms (lambda::symbol->new ("!"), $atom);
		$lambda::undefined;
	}
	sub value_Ge {
		my $atom = shift;
		my $list = $atom->{value};
		my $first = $list->{first};
		my $op = $first->{next};
		my $third = $op->{next};
		$list->{first} = $op->{before} = $third;
		$list->{last} = $op->{next} = $first;
		$first->{before} = $third->{next} = $op;
		delete $first->{next};
		delete $third->{before};
		$op->{return} = $op->{value} = lambda::symbol->new ("<=");
		$atom->analyzeCommandList;
	}
	sub value_Gt {
		my $atom = shift;
		my $op = $atom->second;
		$op->{return} = $op->{value} = lambda::symbol->new ("<=");
		my $result = $atom->analyzeCommandList;
		$result->isError ? $result : _valueInv ($atom);
	}
	sub value_Lt {
		my $atom = shift;
		my $result = value_Ge ($atom);
		$result->isError ? $result : _valueInv ($atom);
	}
	sub _valueInv {
		my $atom = shift;
		my $new = $atom->newAtomAfter->appendAtoms ("!", $atom);
		$new->fixAnalyze ("boolean_not");
	}
	sub value_changeValue {
		my $atom = shift;
		my ($first, $op, $third) = $atom->firsts (3);
		if ($third->{next}) {
			$atom->newAtomAfter->appendAtoms ($first, $op, $atom);
			return $lambda::undefined;
		} elsif ($third->{value}->isBlock) {
			$third->{value}->toCommandBlock;
			$third->analyze;
			return if $lambda::error;
		}
		my $valueProperty = $third->{return};
		my $value = $valueProperty->{value};
		my $class = $valueProperty->{class};
		my $targetProperty = $first->{return};
		my $tClass = $targetProperty->{class};
		my $v = $class->qName;
		my $t = $tClass->qName;
		if (($v eq "class'value'string'word'") && ($t eq "class'value'string'")) {
			$third->newAtomAfter->appendAtoms ($third, "toString")->fixAnalyze ("data_toString");
		} elsif ($v ne $t) {
			return lambda::error->new (11, $tClass, $class, $value) if ($v ne $t);
		}
		$lambda::undefined;
	}
	sub value_new {
		my $atom = shift;
		my $class = $atom->second->{return}->{value};
		$atom->{return} = lambda::property->new ($class, $class->new);
	}
	sub value_new1 {
		my $atom = shift;
		my ($new, $classAtom, $second) = $atom->firsts (3);
		my $class = $classAtom->{return}->{value};
		my $myProperty = lambda::property->new ($class);
		my $block = $atom->newAtomAfter;
		$block->{value} = lambda::commandBlock->new;
		$block->{isolate} = 1;
		$block->{value}->{properties}->{my} = $block->{return} = $myProperty;
		$block->appendAtoms ("list");
		my $first = $block->first;
		$first->appendAtoms ($lambda::my->quote, ":= list");
		my $last = $first->last;
		$last->appendAtoms ($new, $classAtom);
		$last->fixAnalyze ("value_new", $myProperty);
		$first->first->{return} = $myProperty;
		$first->fixAnalyze ("value_changeValue");
		my $class0;
		if ((! $second->{return}->isSymbol)) {
			$block->appendAtoms ("list");
			my $copy = $block->last;
			$copy->appendAtoms ($second, "copyTo", $lambda::my);
			$copy->last->{return} = $myProperty;
			$copy->fixAnalyze ("value_copyTo");
			return if $lambda::error;
		}
		if ($atom->first) {
			$block->appendAtoms ($atom);
			$last = $block->last;
			my $new = $last->insertAsFirst ($lambda::my);
			$new->{return} = $myProperty;
			$last->changeValues;
			return if $lambda::error;
		} else {
			$atom->erase;
		}
		$block->appendAtoms ("list");
		$last = $block->last;
		$last->appendAtoms ($lambda::my);
		$last->fixAnalyze ("data_value");
		while ($class && (! $class0 || ($class0 ne $class))) {
			my @init = @{$class->{init}};
			foreach my $initBlock (@init) {
				my $new = $last->newAtomBefore;
				$new->setValue ($initBlock->copy);
				$new->{value}->changeAllProperties ($initBlock->{properties}->{my}, $myProperty);
				delete $new->{value}->{properties}->{my};
			}
			$class = $class->{class};
		}
		$myProperty;
	}
	sub value_new2 {
		my $atom = shift;
		my ($first, $second, $third) = $atom->firsts (3);
		return $lambda::empty if $second->{return}->{value}->isClass;
		my $class = $second->{return}->{class}->{class};
		my $class0 = $third->{return}->{value};
		return lambda::error->new (66, $class, $class0) if ! $class0->isASubclass ($class);
		my $symbol = $second->{value};
		return lambda::error->new (2, $symbol) if ! $symbol->isSymbol;
		$symbol->{quote} = 1;
		my $new = $atom->newAtomAfter;
		$new->appendAtoms ($symbol, ":=", $atom);
		$atom->third->newAtomAfter->appendAtoms ($second, "above")->fixAnalyze ("data_above");
		return if $lambda::error;
		my $property = $new->third->fixAnalyze ("value_new1");
		return if $lambda::error;
		$new->first->{return} = $new->defSymbol ($symbol, $property->copy);
		return if $lambda::error;
		$new->fixAnalyze ("value_changeValue", $lambda::undefined);
	}
	sub value_forEach {
		my $atom = shift;
		my ($p1, $p2, $p3, $p4, $p5, $block) = $atom->firsts (6);
		return lambda::error->new (2, $p2) if ! $p2->{value}->isSymbol;
		my $property = $p2->{return};
		my $new = $atom->newAtomAfter->appendAtoms ($p2, ":=", $p3);
		$new->analyze;
		return if $lambda::error;
		$property = $new->first->{return};
		$new = $new->newAtomAfter->appendAtoms ("repeat dBlock");
		my $repeatBlock = $new->second->appendAtoms ("list list");
		my $if = $repeatBlock->first;
		$if->appendAtoms ("if list", $block, "dBlock");
		my $var = lambda::atom->new;
		$var->setValue ($p2->{value}, $property);
		$if->second->appendAtoms ($var, "<=", $p5);
		my $quit = $if->fourth;
		$quit->appendAtoms ("list");
		$quit->first->appendAtoms ("quit");
		my $add = $repeatBlock->second;
		$add->appendAtoms ($var, ":= list");
		$add->third->appendAtoms ($var, "+", $p4);
		$atom->erase;
		$lambda::undefined;
	}
	sub value_ifBlock {
		my $atom = shift;
		my ($if, $v0, $third) = $atom->firsts (3);
		my $eq = $third->{return}->isSymbol ? $third->detach : lambda::symbol->new ("=");
		my $newAtom = $atom->newAtomAfter;
		$newAtom->{value} = lambda::commandBlock->new;
		$newAtom->appendAtoms ("list", $atom);
		my $temp = lambda::symbol->new;
		my $first = $newAtom->first;
		$first->appendAtoms ($temp, ":=", $v0);
		my $property = $first->first->{return} = lambda::property->new ($v0->{return}->{class}->new);
		$first->fixAnalyze ("value_changeValue");
		my $value = $first->{next}->second;
		while ($value && $value->{return} && $value->{return}->isProperty) {
			my $comp = $value->newAtomAfter;
			$comp->appendAtoms ($temp, $eq, $value);
			$comp->first->{return} = $property;
			$comp->analyze;
			return if $lambda::error;
			my $block = $comp->{next};
			$value = $block->{next};
		}
		$newAtom->second->fixAnalyze ("boolean_ifBlock");
	}
	sub value_ifValue {
		my $atom = shift;
		my $third = $atom->third;
		my $op = $third->{return};
		$op->isSymbol ? $third->erase : ($op = lambda::symbol->new ("="));
		my ($if, $c0, $c1, $v1, $c2, $v2) = $atom->firsts (7);
		my $newBlock = $atom->newAtomAfter;
		$newBlock->{value} = lambda::commandBlock->new;
		my $temp = lambda::symbol->new;
		$newBlock->appendAtoms ("list list");
		my $newAtom = $newBlock->first;
		$newAtom->appendAtoms ($temp, ":=", $c0);
		$newAtom->fixAnalyze ("value_defVar");
		$newAtom = $newAtom->{next};
		$newAtom->appendAtoms ($if);
		while (1) {
			$newAtom->appendValues (lambda::list->new);
			my $comp = $newAtom->last;
			$comp->appendValues ($temp);
			$comp->appendAtoms ($op, $c1);
			$comp->analyze;
			$newAtom->appendAtoms ($v1);
			if ($v2) {
				$c1 = $c2;
				$v1 = $v2;
				$c2 = $v2->{next};
				$v2 = $c2->{next};
			} else {
				$newAtom->appendAtoms ($c2);
				$atom->erase;
				last;
			}
		}
		$newAtom->fixAnalyze ("boolean_ifValue");
	}
	sub value_minmax {
		my $atom = shift;
		my ($op, $a1, $a2, $a3) = $atom->firsts (4);
		my $symbol = $op->{value};
		if ($a3) {
			my $new = $atom->newAtomAfter;
			$new->appendAtoms ($symbol, $a1, $atom);
			$new->third->analyzeCommandList;
			return $lambda::error ? $lambda::error : $new->fixAnalyze ("value_minmax");
		}
		my $script = $symbol->{value} eq "min" ?
			"if (&1 isEmpty) &2 (&2 isEmpty) &1 (if (&1 <= &2) &1 &2);" :
			"if (&1 isEmpty) &2 (&2 isEmpty) &1 (if (&2 <= &1) &1 &2);";
		$atom->microScript ($script, $a1, $a2);
	}
	sub value_type {
		my $result = shift->first->analyze;
		$result->isError ? $result : lambda::property->new ($lambda::master::class, $result->{class});
	}
	sub value_isClass {
		my $atom = shift;
		my $name1 = $atom->first->{return}->{class}->{name};
		my $name2 = $atom->third->{return}->{value}->{name};
		my $bool = $atom->{value} = $name1 eq $name2 ? $lambda::true : $lambda::false;
		lambda::property->new ($bool);
	}
	sub value_copyTo {
		my ($first, $second, $third) = shift->firsts(3);
		my $source = $first->{return}->{class};
		my $target = $third->{return}->{class};
		$target->isASubclass ($source) ? $lambda::undefined : lambda::error->new (66, $source, $target);
	}
	sub value_downgrade1 {
		my $atom = shift;
		my ($valueAtom, $classAtom) = $atom->firsts (2);
		my $last = $classAtom->newAtomAfter;
		my $className = $classAtom->{value}->{value};
		$className =~ s/^to//;
		$classAtom->{value} = $classAtom->{return} = lambda::symbol->new ("to");
		my $classProperty = $last->{return} = $atom->findSymbol (lambda::symbol->new (lcfirst ($className)));
		my $class = $last->{value} = $classProperty->{value};
		$atom->fixAnalyze ("value_downgrade", lambda::property->new($class));
	}
package lambda::command;
	sub value_new {
		shift->second->{return}->{value}->new;
	}
	sub value_modify {
		my ($atom, $value, @p) = @_;
		my $properties = $value->{properties};
		while (@p) {
			my $n = (shift @p)->{value};
			my $v = shift @p;
			my $property = $properties->{$n};
			$property = $value->{properties}->{$n} = $value->{class}->property ($n)->copy if ! $property;
			$v->isClass ? $property->{value} = $v : $property->changeValue ($v, $atom);
		}
		$value;
	}
	sub value_empty {
		shift->{return}->{value};
	}
	sub value_isA {
		shift->{return}->{value};
	}
	sub value_defRef {
		my ($first, $second, $third) = shift->firsts (3);
		$first->{return}->{pointer} = $third->{return};
		$lambda::undefined;
	}
	sub value_eq {
		my ($atom, $v1, $op, $v2, $class) = @_;
		return $lambda::true if $v1 eq $v2 || ($v1->isEmpty && $v2->isEmpty);
		return $lambda::false if $v1->isEmpty || $v2->isEmpty;
		$class = $v1->{class} if ! $class;
		while ($class->isClass) {
			if ($class->{internally}) {
				my $name = "lambda::classes::" . $class->{name};
				my $call = $name->can ("eq");
				if ($call) {
					my $action = \&$call;
					my $return = $action->($v1, $v2);
					return $return if $return->isFalse;
				} else {
					return $lambda::false if $v1->{value} ne $v2->{value};
				}
			} else {
				foreach (keys %{$class->{properties}}) {
					return $lambda::false if value_eq ($atom, $v1->property ($_)->{value}, $op, $v2->property ($_)->{value})->isFalse;
				}
			}
			$class = $class->{class};
		}
		$lambda::true;
	}
	sub value_ne {!value_eq (@_)}
	sub value_isEmpty {shift; shift->isEmpty ? $lambda::true : $lambda::false}
	sub value_isNotEmpty {shift; shift->isEmpty ? $lambda::false : $lambda::true}
	sub value_changeValue {
		my ($atom, $result, $op, $value) = @_;
		my $property = $atom->first->{return};
		my $device = $property->{value}->{device};
		$property = $property->{pointer} if $property->{pointer};
		if ($value->isFunctional) {
			$property->{value} = $atom->third->detach;
		} else {
			$property->changeValue ($value->copy, $atom);
		}
		$lambda::undefined;
	}
	sub value_evaluate {
		shift;
		shift;
	}
	sub value_type {
		shift->{return}->{value};
	}
	sub value_clone {
		my ($atom, $value, $op, $class) = @_;
		$op->isSymbol ? $value->copy ($class) : $op->copy ($class);
	}
	sub value_isClass {
		shift->{return}->{value};
	}
	sub value_copyTo {
		my ($atom, $source, $second, $target) = @_;
		$source->copyTo ($target);
		while (my ($key, $property) = each %{$source->{properties}}) {
			next if $target->property ($key)->isUndefined;
			$target->{properties}->{$key} = $property->copy;
		}
		$atom->third->{return}->changeValue ($target, $atom);
		$lambda::undefined;
	}
	sub value_downgrade {
		my ($atom, $source, $op, $class) = @_;
		my $target = $class->new;
		$class = $class->{class} while ! $class->{intern};
		my $copyTo = "lambda::classes::" . $class->{name} . "::copyTo";
		my $code = main->can ($copyTo);
		(\&$code)->($source, $target);
		foreach (keys %{$target->{properties}}) {
			$target->{properties}->{$_} = $source->{properties}->{$_}->copy;
		}
		$target;
	}
package lambda;
	no warnings 'qw';
	push (@lambda::master::functions, qw (
		record_new record new,record,@symbol,data,(@symbol,data)
		record_getProperty . record,@symbol
		record_keys . record,keys;keys,record
		record_toString string record,toString
	));
package lambda::clsRecord;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
	sub new {lambda::classes::record->new (@_)}
package lambda::classes::record;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift;
		$self;
	}
	sub string {
		my $self = shift;
		my $properties = $self->{properties};
		return "{empty}" if ! $properties;
		my @array = ();
		foreach (sort keys %{$properties}) {
			push @array, $_ . "=>" . $properties->{$_}->{value}->string;
		}
		"{" . join (", ", @array) ."}";
	}
package lambda::init;
	sub record_new {
		my $atom = shift;
		my $record = $lambda::master::record->new;
		my ($new, $class, $symbol) = $atom->firsts (3);
		$new->erase;
		while ($symbol) {
			my $data = $symbol->{next};
			my $name = $symbol->{value}->{value};
			$record->{properties}->{$name} = $data->{return};
			$symbol = $data->{next};
		}
		$class->newAtomAfter->setValue ($record, lambda::property->new ($record));
		$class->erase;
		$atom->fixAnalyze ("value_modify");
	}
	sub record_getProperty {
		my $atom = shift;
		my ($recordATom, $symbolAtom) = $atom->firsts (2);
		my $record = $recordATom->{return}->{value};
		my $name = $symbolAtom->{value}->{value};
		my $property = $record->{properties}->{$name};
		return lambda::error->new (28, $name, $record) if ! $property;
		$atom->fixAnalyze ("data_getProperty");
	}
	sub record_keys {
		my $keys = $lambda::master::stack->new;
		$keys->modifyProperty ("of", $lambda::master::word);
		lambda::property->new ($keys);
	}
package lambda::command;
	sub record_toString {
		my ($atom, $record, $symbol) = @_;
		$lambda::master::string->new ($record->string);
	}
	sub record_keys {
		my ($atom, $record, $op) = @_;
		$record = $op if $record->isSymbol;
		my @keys = ();
		push @keys, lambda::property->new ($lambda::master::word->new ($_)) foreach sort keys %{$record->{properties}};
		my $array = $atom->{return}->{value};
		$array->{value} = \@keys;
		$array;
	}
package lambda;
	push (@lambda::master::functions, qw (
		task_terminate . task,terminate;terminate
		task_stop . stop
	));
package lambda::clsTask;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
	sub new {lambda::classes::task->new (@_)}
package lambda::classes::task;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift;
		$self->{value} = shift;
		$self;
	}
	sub string {
		my $task = shift;
		return lambda::empty->string ($task) if $task->isEmpty;
		if ($task->{value} && $task->{value}->{value}) {
			my $s = $task->{value}->{value}->string;
			$s =~ s/^\{//;
			return "{task: $s";
		}
		"{task:}";
	}
package lambda::command;
	sub task_terminate {
		my ($atom, $task, $op) = @_;
		return $lambda::terminate if ! defined $op;
		my $thread = $task->{value};
		$thread->insertAsFirst ($op)->fixAnalyze ("task_terminate");
		$lambda::undefined;
	}
	sub task_stop {
		main::lambda_Stop (shift->lambda->{hash}, "stopped", undef);
		$lambda::undefined;
	}
package lambda;
	push (@lambda::master::functions, qw (
		regExpr_match boolean string,~,regExpr
		regExpr_notMatch boolean string,!~,regExpr
	));
	push (@lambda::master::functions1, qw (
		regExpr_new regExpr new,#regExpr
	));
	$lambda::error::msgE{"regExpr_01"} = "new regExpr; - nicht zulässig! regExpr kann keine leere Zeichenkette sein.";
package lambda::base;
	sub isRegExpr {}
package lambda::clsRegExpr;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
	sub new {lambda::classes::regExpr->new (@_)}
package lambda::classes::regExpr;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift;
		$self->{value} = shift;
		$self;
	}
	sub string {shift->{value}}
	sub isRegExpr {1}
package lambda::init;
	sub regExpr_new {
		my $second = shift->second;
		$second->{return}->{value} eq $lambda::master::regExpr ?
			lambda::error->new ("regExpr_01") : lambda::empty->new;
	}
package lambda::command;
	sub regExpr_match {
		my ($atom, $string, $op, $pattern) = @_;
		return $lambda::false if $string->isEmpty;
		my $result;
		my $value = $string->{value};
		eval "\$result = \$string->{value} =~ $pattern->{value}";
		$atom->lambda->putChangedProperty ($atom->first->{return}) if $value ne $string->{value};
		$result ? $lambda::true : $lambda::false;
	}
	sub regExpr_notMatch {regExpr_match (@_)->isFalse ? $lambda::true : $lambda::false}
	sub regExpr_new {$lambda::undefined}
package lambda;
	push (@lambda::master::functions, qw (
		string_plus string string,+,string;
		string_le boolean string#,<=,string#
		string_multiply string number#,*,string
		word_multiply word number#,*,word
		string_toMoment moment string#,toMoment
		string_isNumber boolean string,isNumber
		string_toNumber number string#,toNumber
		string_toNumber1 number string,toNumber,alternatively,number
		string_isTimespan boolean string,isTimespan
		string_toTimespan timespan string,toTimespan
		string_toTimespan1 timespan string,toTimespan,alternatively,timespan
	));
	$lambda::error::msgE{"string_01"} = "&&1 ist keine Zahl!";
	$lambda::error::msgE{"string_02"} = "&&1 ist keine Zeitspanne!";
package lambda::base;
	sub isClsString {}
	sub isString {}
package lambda::value;
	sub isString {shift->{class}->isASubclass ($lambda::master::string)};
package lambda::clsString;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
	sub new {lambda::classes::string->new (@_)}
	sub isClsString {1}
package lambda::classes::string;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub isString {1}
	sub new {
		my $self = bless {}, shift;
		($self->{class}, my $value) = @_;
		$value = "" if !defined $value;
		$self->{value} = $value;
		$self;
	}
	sub compare {
		my ($a1, $b1) = @_;
		return 1 if ! $b1->isString;
		my $a = $a1->{value};
		my $b = $b1->{value};
		$a ? ($b ? $a cmp $b : -1) : ($b ? 1 : 0);
	}
	sub string {
		shift->{value};
	}
package lambda::command;
	sub string_le {
		($_[1]->{value} cmp $_[3]->{value}) <= 0 ? $lambda::true : $lambda::false;
	}
	sub string_plus {
		my ($atom, $a, $op, $b) = @_;
		return $b if $a->isEmpty;
		return $a if $b->isEmpty;
		$lambda::master::string->new ($a->{value} . $b->{value});
	}
	sub _string_multiply {
		my ($number, $v) = @_;
		my $n = $number->{num};
		return lambda::error->new (17, "0", $number) if ! $number->{den}->isOne || $n->{sign};
		return "" if $n->isZero;
		my $b = $v;
		my $result;
		while (1) {
			$result = $result ? $result . $b : $b if $n->isOdd;
			$n = $n->div2;
			return $result if $n->isZero;
			$b .= $b;
		}
	}
	sub string_multiply {
		my ($atom, $number, $op, $string) = @_;
		$lambda::master::string->new (_string_multiply ($number, $string->{value}));
	}
	sub string_toMoment {
		my ($atom, $string) = @_;
		if ($string =~ /(\d{1,2})\.(\d{1,2})\.(\d{1,4})\s?(\d{1,2}):?(\d{1,2}),?(\d{1,2})/) {
			my $moment = $lambda::master::moment->new (Time::Local::timelocal ($6, $5, $4, $3, $2 - 1, $1));
			return $! ? lambda::error->new (81, $string) : $moment;
		} else {
			return $lambda::master::moment->new;
		}
	}
	sub string_isNumber {
		string_toNumber (@_)->isNumber ? $lambda::true : $lambda::false;
	}
	sub string_toNumber {
		my ($atom, $string) = @_;
		my $s = $string->{value} || "";
		$s =~ s/^\s+|\s+$//g;
		return $lambda::master::number->new if ! $s;
		my $data = lambda::atom::valueFromString ($s);
		$data->isNumber ? $data : lambda::error->new ("string_01", $string);
	}
	sub string_toNumber1 {
		my ($atom, $string, $op, $or, $number) = @_;
		return $number if $string->isEmpty;
		my $data = string_toNumber ($atom, $string);
		$data->isNumber ? $data : $number;
	}
	sub string_isTimespan {
		string_toTimespan (@_)->isError ? $lambda::false : $lambda::true;
	}
	sub string_toTimespan {
		my ($atom, $string) = @_;
		my $s = $string->{value} || "";
		$s =~ s/^\s+|\s+$//g;
		return $lambda::master::timespan->new if ! $s;
		my $data = lambda::atom::valueFromString ($s);
		$data->isTimespan ? $data : lambda::error->new ("string_02", $string);
	}
	sub string_toTimespan1 {
		my ($atom, $string, $op, $or, $value) = @_;
		my $data = string_toTimespan ($atom, $string);
		$data->isError ? $value : $data;
	}
package lambda;
	push (@lambda::master::functions, qw (
		word_plus word word,+,word
		string_toWord word string,toWord
	));
	push (@lambda::master::functions1, qw (
		word_new word new,word
	));
	$lambda::error::msgE{"word_01"} = "new word; - nicht zulässig! Inhalt kann keine leere Zeichenkette sein.";
	$lambda::error::msgE{"word_02"} = "new word &&1; - nicht zulässig! Enthält Leerzeichen.";
	$lambda::error::msgE{"word_03"} = "Faktor vor &&1 darf nicht 0 sein!";
package lambda::base;
	sub isWord {}
package lambda::value;
	sub isWord {shift->{class}->isASubclass ($lambda::master::word)};
package lambda::clsWord;
	use vars ('@ISA');
	@ISA = qw (lambda::clsString);
	sub new {lambda::classes::word->new (@_)}
package lambda::classes::word;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::string);
	sub isWord {1}
	sub new {
		my $self = bless {}, shift;
		($self->{class}, $self->{value}) = @_;
		$self;
	}
package lambda::init;
	sub word_new {
		lambda::error->new ("word_01")
	}
package lambda::command;
	sub word_plus {
		my ($atom, $a, $op, $b) = @_;
		return $b if $a->isEmpty;
		return $a if $b->isEmpty;
		$lambda::master::word->new ($a->{value} . $b->{value});
	}
	sub string_toWord {
		my $s = $_[1]->{value};
		return lambda::error->new ("word_02", $s) if $s =~ m/\s/;
		$lambda::master::word->new ($s);
	}
	sub word_multiply {
		my ($atom, $number, $op, $word) = @_;
		my $n = $number->{num};
		return lambda::error->new ("word_03", $word) if $n->isZero;
		$lambda::master::word->new (_string_multiply ($number, $word->{value}));
	}
package lambda::base;
	sub isNumber {}
	sub isInteger {}
	sub isNotNegInteger {}
	sub isNotPosInteger {}
	sub isPosInteger {}
	sub isNegInteger {}
package lambda;
	push (@lambda::master::functions, qw (
		number_plus1 number number#,+;number#,++;number#,+++
		number_minus1 number number#,-;number#,--;number#,---
		number_switchSign number -,number#
		number_inverse number number,^-1
		number_plus number number#,+,number#
		number_mult number number#,*,number#
		number_multiply number number#,^,number#
		number_isNatural boolean number#,isNatural
		number_isInteger boolean number#,isInteger
		number_le boolean number#,<=,number#
		number_random1 number random,number#
		number_random2 number random,number#,number#
		number_round number round,number#;number#,round
		number_forEach . forEach,number@symbol,number#,@block;forEach,number@symbol,number#,number#,@block
	));
	$lambda::error::msgE{"number_01"} = "Fehlerhafter Formatstring &&1: &&2";
	$lambda::error::msgE{"number_02"} = "0 ^ 0 nicht definiert!";
package lambda::clsNumber;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
	sub new {
		lambda::classes::number->new (@_);
	}
	sub newFromString {
		lambda::classes::number->newFromString (@_);
	}
	sub init {
		my $class = shift;
		$lambda::master->defProperty ($class, "format", lambda::property->new ($lambda::master::string->new));
	}
package lambda::classes::number;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub newFromString {
		shift;
		my $class = shift;
		my $num = lambda::integer->stringToInteger (shift || 0);
		my $den = lambda::integer->stringToInteger (shift || 1)->toNatural;
		lambda::classes::number->new ($class, $num, $den);
	}
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift;
		my $num = shift || lambda::integer->new;
		my $den = shift || lambda::natural->new (1);
		($self->{num}, $self->{den}) = fractionReduce ($num, $den);
		$self->{format} = $lambda::emptyString;
		$self;
	}
	sub eq {
		compare (@_) ? $lambda::false : $lambda::true;
	}
	sub compare {
		my ($x, $y) = @_;
		return 0 if $x eq $y;
		return 1 if ! $y->isNumber;
		my $nx = $x->{num};
		my $ny = $y->{num};
		my $vx = $nx->{sign};
		my $vy = $ny->{sign};
		return -1 if $vx && ! $vy;
		return 1 if ! $vx && $vy;
		my $zx = $nx->{z} ? scalar @{$nx->{z}} : 0;
		my $zy = $ny->{z} ? scalar @{$ny->{z}} : 0;
		if ($vx) {
			return 1 if $zx < $zy;
			return -1 if $zx > $zy;
		} else {
			return 1 if $zx > $zy;
			return -1 if $zx < $zy;
		}
		my $u = $nx->mult ($y->{den})->toNatural;
		my $v = $ny->mult ($x->{den})->toNatural;
		my @zu = @{$u->{z}};
		my @zv = @{$v->{z}};
		my $nu = scalar @zu;
		my $nv = scalar @zv;
		if ($nu < $nv) {
			return $vx ? 1 : -1;
		} elsif ($nu == $nv) {
			while ($nu) {
				--$nu;
				my $c = $zu[$nu] <=> $zv[$nu];
				return $vx ? -$c : $c if $c;
			}
			return 0;
		} else {
			return $vx ? -1 : 1;
		}
	}
	sub multInteger {
		my $self = shift;
		my $f = lambda::natural->new (@_);
		($self->{den}, $f) = fractionReduce ($self->{den}, $f);
		$self->{num} = $self->{num}->mult ($f);
		$self;
	}
	sub divInteger {
		my $self = shift;
		my $f = lambda::natural->new (@_);
		($self->{num}, $f) = fractionReduce ($self->{num}, $f);
		$self->{den} = $f->mult ($self->{den});
		$self;
	}
	sub plus {
		my ($p1, $p2) = @_;
		my $den1 = $p1->{den};
		my $den2 = $p2->{den};
		my $num1 = $p1->{num}->mult ($den2);
		my $num2 = $p2->{num}->mult ($den1);
		my $num = $num1->add ($num2);
		my $den =  $den1->mult ($den2);
		$lambda::master::number->new ($num, $den);
	}
	sub minus {
		my ($p1, $p2) = @_;
		my $den1 = $p1 ->{den};
		my $den2 = $p2 ->{den};
		$lambda::master::number->new ($p1->{num}->mult ($den2)->diff ($p2->{num}->mult ($den1)), $den1->mult ($den2));
	}
	sub mult {
		my ($a, $b) = @_;
		$lambda::master::number->new ($a->{num}->mult ($b->{num}), $a->{den}->mult ($b->{den}));
	}
	sub divi {
		my ($a, $b) = @_;
		return lambda::error->new (18) if $b->{num}->isZero;
		$lambda::master::number->new ($a->{num}->mult ($b->{den}), $a->{den}->mult ($b->{num}));
	}
	sub inverse {
		my $self = shift;
		return lambda::error->new (18) if (my $h = $self->{num})->isZero;
		$self->{num} = $self->{den}->toInteger ($h->{sign});
		$self->{den} = $h->toNatural;
		$self;
	}
	sub switchSign {
		my $self = shift;
		$self->{num}->switchSign;
		$self;
	}
	sub multiply {
		my ($p1, $p2) = @_;
		return lambda::error->new (4, $p2) if ! $p2->{den}->isOne;
		my $n = $p2->{num};
		return $p1->{num}->isZero ? lambda::error->new ("number_02") : $lambda::one if $n->isZero;
		my $bb = $n->{sign} ? $p1->inverse->copy : $p1->copy;
		$n = $n->toNatural->copy;
		my $result;
		while (1) {
			$result = $result ? $result->mult ($bb) : $bb if $n->isOdd;
			$n = $n->div2;
			return $result if $n->isZero;
			$bb = $bb->mult ($bb);
		}
	}
	sub copyTo {
		my ($from, $to) = @_;
		$to->{num} = $from->{num}->copy;
		$to->{den} = $from->{den}->copy;
		$to->{format} = $from->{format}->copy;
	}
	sub fractionReduce {
		my ($num, $den) = @_;
		if ($den->{sign}) {
			$num->{sign} = $num->{sign} ? 0 : 1;
			delete $den->{sign};
		}
		my $ggt = $num->toNatural->ggt ($den->toNatural);
		if (! $ggt->isOne) {
			($num) = $num->div ($ggt);
			($den) = $den->div ($ggt);
		}
		($num, $den);
	}
	sub int {
		my $self = shift;
		my ($a, $b) = $self->{num}->div ($self->{den});
		$lambda::master::number->new ($a);
	}
	sub string {
		my $number = shift;
		my $value = $number->{den}->isOne ? $number->{num}->string : lambda::classes::number::value ($number);
		my $format = $number->property ("format")->{value}->{value};
		return $value if ! $format;
		my $r = eval "sprintf(\"" . $format . "\"," . $value . ")";
		$@ ? lambda::error->new ("number_01", $r, $@) : $r;
	}
	sub value {
		my $self = shift;
		$self->{num}->string / $self->{den}->string;
	}
	sub isNumber {1}
	sub isInteger {shift->{den}->isOne}
	sub isNotNegInteger {
		my $self = shift;
		$self->isInteger && ! $self->{num}->{sign};
	}
	sub isNegInteger {
		my $self = shift;
		$self->isInteger && $self->{num}->{sign};
	}
	sub isPosInteger {
		my $self = shift;
		my $num = $self->{num};
		$self->isInteger && ! $num->{sign} && ! $num->isZero;
	}
	sub isNotPosInteger {
		my $self = shift;
		my $num = $self->{num};
		return 1 if ! $self->isInteger;
		$num->{sign} || $num->isZero;
	}
package lambda::value;
	sub isNumber {shift->{class}->isASubclass ($lambda::master::number)}
package lambda::init;
	sub number_switchSign {
		shift->second->{return}->copy;
	}
	sub number_plus1 {
		number_minus1 (@_);
	}
	sub number_minus1 {
		my $return = shift->first->{return};
		$return->{value}->isConstant ? lambda::error->new ("value_07") : $return;
	}
	sub number_forEach {
		my $atom = shift;
		my ($forEach, $var, $start, $end, $block) = $atom->firsts (5);
		if (! $block) {
			$start = $var->newAtomAfter;
			$start->setValue ($lambda::master::number->newFromString (1));
		}
		$start->newAtomAfter->setValue ($lambda::master::number->newFromString (1));
		$atom->fixAnalyze ("value_forEach");
	}
	sub number_repeatTimes {
		my $atom = shift;
		my $n = $atom->first->newAtomAfter;
		my $e = $n->{return} = lambda::property->new ($lambda::master::timespan);
		$n->{value} = $e->{value};
		$n = $atom->first->newAtomAfter;
		$e = $n->{return} = lambda::property->new ($lambda::master::moment);
		$n->{value} = $e->{value};
		$atom->analyze;
	}
package lambda::command;
	sub number_le {lambda::classes::number::compare ($_[1], $_[3]) <= 0 ? $lambda::true : $lambda::false}
	sub number_plus1 {
		my ($atom, $self, $op) = @_;
		my $n = length ($op->{value});
		while ($n) {
			$self->{num} = lambda::integer::add ($self->{num}, $self->{den});
			$n--;
		}
		$atom->lambda->putChangedProperty ($atom->first->{return});
		$self;
	}
	sub number_minus1 {
		my ($atom, $self, $op) = @_;
		my $n = length ($op->{value});
		while ($n) {
			$self->{num} = lambda::integer::diff ($self->{num}, $self->{den});
			$n--;
		}
		$atom->lambda->putChangedProperty ($atom->first->{return});
		$self;
	}
	sub number_plus {
		my ($atom, $p1, $op, $p2) = @_;
		lambda::classes::number::plus ($p1, $p2);
	}
	sub number_mult {
		my ($atom, $a, $op, $b) = @_;
		lambda::classes::number::mult ($a, $b);
	}
	sub number_switchSign {
		my ($atom, $op, $number) = @_;
		$number->switchSign;
	}
	sub number_inverse {
		my ($atom, $p1, $p2) = @_;
		$p2->isSymbol ? $p1->inverse : $p2->inverse;
	}
	sub number_multiply {
		my ($atom, $p1, $op, $p2) = @_;
		lambda::classes::number::multiply ($p1, $p2);
	}
	sub number_isNatural {
		my ($atom, $self) = @_;
		$self->isPosInteger ? $lambda::true : $lambda::false;
	}
	sub number_isInteger {
		my ($atom, $self) = @_;
		$self->isInteger ? $lambda::true : $lambda::false;
	}
	sub number_random1 {
		my ($atom, $op, $value1) = @_;
		return lambda::error->new (17, "0", $value1) if $value1->isNotPosInteger;
		my $r = $lambda::master::number->newFromString (int (lambda::natural::base * rand ()), lambda::natural::base);
		$r = $r->mult ($value1);
		$r->{num} = $r->{num}->add ($r->{den});
		$r->int;
	}
	sub number_random2 {
		my ($atom, $op, $value1, $value2) = @_;
		return lambda::error->new (4, $value1) if ! $value1->isInteger;
		return lambda::error->new (4, $value2) if ! $value2->isInteger;
		my $d = $value2->minus ($value1);
		return lambda::error->new (4, $value1, $value2) if $d->isNotPosInteger;
		my $r = $lambda::master::number->newFromString (int (lambda::natural::base * rand ()), lambda::natural::base);
		$r->mult ($d)->plus ($value1)->int;
	}
	sub number_round {
		my ($atom, $number, $symbol) = @_;
		$number = $symbol if $number->isSymbol;
		$lambda::master::number->newFromString (sprintf ("%.0f", $number->string))
	}
package lambda;
	push (@lambda::master::functions, qw (
		unitOfMeasurement_new2 unitOfMeasurement [,@symbol,]
	));
	push (@lambda::master::functions1, qw (
		unitOfMeasurement_new1 unitOfMeasurement new,#unitOfMeasurement,@symbol;
	));
	$lambda::error::msgE{"unitOfMeasurement_01"} = "Unzulässige Einheit: &&1";
package lambda::base;
	sub isClsUnitOfMeasurement {}
package lambda::clsUnitOfMeasurement;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
	sub new {lambda::classes::unitOfMeasurement->new (@_)}
	sub isClsUnitOfMeasurement {1}
package lambda::classes::unitOfMeasurement;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift;
		my $unit = my $unit0 = shift || "";
		my @dimension = qw (m g s A K mol cd €);
		my @h = ();
		push @h, 0 foreach @dimension;
		my $p = 0;
		$unit =~ s/\s+//g;
		$self->{name} = $unit;
		my $notSI;
		my $noExp;
		my $exp;
		my @f = (1, 1);
		my @z = (0, 1);
		while ($unit) {
			my $prefix = 1;
			$unit =~ s/^(.*?)([+-]?\d+)?$/$1/;
			$exp = $2 || 1;
			my $base = "";
			if ($unit =~ s/^ct$//) {$base = "€"; @f = (1, 100); undef $prefix}
			elsif ($unit =~ s/^°C$//) {$h[4]++; @z = (5463, 20); $noExp = 1; $notSI = 1; undef $prefix; last}
			elsif ($unit =~ s/^°F$//) {$h[4]++; @f = (5, 9); @z = (45967, 100); $noExp = 1; $notSI = 1; undef $prefix; last}
			elsif ($unit =~ s/Ohm$//) {$base = "m2kgs-3A-2"}
			elsif ($unit =~ s/lm$//) {$base = "cd"}
			elsif ($unit =~ s/m$//) {$h[0] += $exp}
			elsif ($unit =~ s/g$//) {$h[1] += $exp; $p -= 3 * $exp}
			elsif ($unit =~ s/s$//) {$h[2] += $exp}
			elsif ($unit =~ s/A$//) {$h[3] += $exp}
			elsif ($unit =~ s/K$//) {$h[4] += $exp}
			elsif ($unit =~ s/mol$//) {$h[5] += $exp}
			elsif ($unit =~ s/cd$//) {$h[6] += $exp}
			elsif ($unit =~ s/€$//) {$h[7] += $exp; undef $prefix}
			elsif ($unit =~ s/Hz$//) {$base = "s-1"}
			elsif ($unit =~ s/N$//) {$base = "kgm1s-2"}
			elsif ($unit =~ s/W$//) {$base = "kgm2s-3"}
			elsif ($unit =~ s/J$//) {$base = "kgm2s-2"}
			elsif ($unit =~ s/Pa$//) {$base = "kgm-1s-2"}
			elsif ($unit =~ s/C$//) {$base = "sA"}
			elsif ($unit =~ s/V$//) {$base = "m2kgs-3A-1"}
			elsif ($unit =~ s/F$//) {$base = "m-2kg-1s4A2"}
			elsif ($unit =~ s/S$//) {$base = "m-2kg-1s3A2"}
			elsif ($unit =~ s/Wb$//) {$base = "m2kgs-2A-1"}
			elsif ($unit =~ s/T$//) {$base = "kgs-2A-1"}
			elsif ($unit =~ s/H$//) {$base = "m2kgs-2A-2"}
			elsif ($unit =~ s/lx$//) {$base = "m-2cd"}
			elsif ($unit =~ s/Bq$//) {$base = "s-1"}
			elsif ($unit =~ s/Gy$//) {$base = "m2s-2"}
			elsif ($unit =~ s/Sv$//) {$base = "m2s-2"}
			elsif ($unit =~ s/kat$//) {$base = "s-1mol"}
			elsif ($unit =~ s/l$//) {$base = "m3"; $h[0] -= 3 * $exp}
			elsif ($unit =~ s/t$//) {$base = "kg"; $h[0] = 3 * $exp}
			elsif ($unit =~ s/bar$//) {$base = "kgm-1s-2"; $h[0] = 5 * $exp}
			elsif ($unit =~ s/min$//) {$base = "s"; @f = (6 ** $exp, 1); $p += $exp; undef $prefix}
			elsif ($unit =~ s/h$//) {$base = "s"; @f = (36 ** $exp, 1); $p += 2 * $exp; undef $prefix}
			elsif ($unit =~ s/d$//) {$base = "s"; @f = (864 ** $exp, 1); $p += 2 * $exp; undef $prefix}
			else {return lambda::error->new ("unitOfMeasurement_01", $unit0)}
			if ($prefix) {
				$unit =~ s/(.*)(Y|Z|E|P|T|G|M|k|h|da|d|c|m|µ|n|p|f|a|z|y)$/$1/;
				if (! $2) {}
				elsif ($2 eq "Y") {$p += 24 * $exp}
				elsif ($2 eq "Z") {$p += 21 * $exp}
				elsif ($2 eq "E") {$p += 18 * $exp}
				elsif ($2 eq "P") {$p += 15 * $exp}
				elsif ($2 eq "T") {$p += 12 * $exp}
				elsif ($2 eq "G") {$p += 9 * $exp}
				elsif ($2 eq "M") {$p += 6 * $exp}
				elsif ($2 eq "k") {$p += 3 * $exp}
				elsif ($2 eq "h") {$p += 2 * $exp}
				elsif ($2 eq "da") {$p += $exp}
				elsif ($2 eq "d") {$p -= $exp}
				elsif ($2 eq "c") {$p -= 2 * $exp}
				elsif ($2 eq "m") {$p -= 3 * $exp}
				elsif ($2 eq "µ") {$p -= 6 * $exp}
				elsif ($2 eq "n") {$p -= 9 * $exp}
				elsif ($2 eq "p") {$p -= 12 * $exp}
				elsif ($2 eq "f") {$p -= 15 * $exp}
				elsif ($2 eq "a") {$p -= 18 * $exp}
				elsif ($2 eq "z") {$p -= 21 * $exp}
				elsif ($2 eq "y") {$p -= 24 * $exp}
			}
			$unit .= $base x $exp if $base;
		}
		return lambda::error->new ("unitOfMeasurement_01", $unit0) if $unit || ($noExp && $exp != 1);
		$self->{n} = $p;
		$self->{dim} = \@h;
		$self->{f} = $lambda::master::number->newFromString (@f);
		$self->{z} = $lambda::master::number->newFromString (@z);
		$self->{notSI} = $notSI;
		$self;
	}
	sub isDimensionless {
		foreach (@{shift->{dim}}) {return if $_}
		return 1;
	}
	sub toSI {
		my $unit = shift;
		delete $unit->{notSI};
		delete $unit->{name};
		$unit->{f} = $lambda::master::number->newFromString (1, 1);
		$unit->{z} = $lambda::master::number->newFromString (0, 1);
		$unit;
	}
	sub string {
		my $self = shift;
		my $s = $self->{name} ? $self->{name} : $self->base;
		"$s";
	}
	sub mult {
		my ($u1, $u2) = @_;
		my @u2 = @{$u2->{dim}};
		my @u = ();
		push (@u, $_ + (shift @u2)) foreach @{$u1->{dim}};
		my $unit = $lambda::master::unitOfMeasurement->new;
		$unit->{dim} = \@u;
		$unit->{n} = $u1->{n} + $u2->{n};
		$unit;
	}
	sub div {shift->mult (shift->inverse)}
	sub inverse0 {
		my $self = shift;
		my @dim = ();
		push (@dim, - $_) foreach @{$self->{dim}};
		my $unit = $lambda::master::unitOfMeasurement->new;
		$unit->{dim} = \@dim;
		$unit->{n} = - $self->{n};
		$unit;
	}
	sub inverse {
		my $self = shift;
		my $unit = $self->toSI;
		$unit = $unit->inverse0;
		$unit;
	}
	sub base {
		my $u = "";
		my @dim = @{shift->{dim}};
		my $d = shift @dim;
		if ($d == 1) {$u .= "m"} elsif ($d) {$u .= "m$d"}
		$d = shift @dim;
		if ($d == 1) {$u .= "kg"} elsif ($d) {$u .= "kg$d"}
		$d = shift @dim;
		if ($d == 1) {$u .= "s"} elsif ($d) {$u .= "s$d"}
		$d = shift @dim;
		if ($d == 1) {$u .= "A"} elsif ($d) {$u .= "A$d"}
		$d = shift @dim;
		if ($d == 1) {$u .= "K"} elsif ($d) {$u .= "K$d"}
		$d = shift @dim;
		if ($d == 1) {$u .= "mol"} elsif ($d) {$u .= "mol$d"}
		$d = shift @dim;
		if ($d == 1) {$u .= "cd"} elsif ($d) {$u .= "cd$d"}
		$d = shift @dim;
		if ($d == 1) {$u .= "€"} elsif ($d) {$u .= "€$d"}
		$u;
	}
	sub signatur {
		my $u = "";
		$u .= $_ ? "$_;" : "0;" foreach @{shift->{dim}};
		$u;
	}
	sub eq {shift->signatur eq shift->signatur}
	sub copyTo {
		my ($old, $new) = @_;
		$new->{dim} = $old->{dim};
		$new->{n} = $old->{n};
		$new->{name} = $old->{name};
		$new->{f} = $old->{f};
		$new->{z} = $old->{z};
		$new->{notSI} = $old->{notSI};
	}
package lambda::init;
	sub unitOfMeasurement_new1 {
		my $atom = shift;
		unitOfMeasurement_new ($atom, $atom->third->{value}->{value});
	}
	sub unitOfMeasurement_new2 {
		my $atom = shift;
		unitOfMeasurement_new ($atom, $atom->second->{value}->{value});
	}
	sub unitOfMeasurement_new {
		my $atom = shift;
		my $unit = $lambda::master::unitOfMeasurement->new (shift);
		return if $lambda::error;
		my $newAtom = $atom->newAtomAfter;
		$newAtom->{return} = lambda::property->new ($newAtom->{value} = $unit);
		$atom->erase;
		$lambda::undefined;
	}
package lambda;
	push (@lambda::master::functions, qw (
		measurement_new measurement [,number,@symbol,];[,number,]
		measurement_multiply measurement measurement,^,number
		measurement_multNumber1 measurement measurement,*,number
		measurement_multNumber2 measurement number,*,measurement
		measurement_plus measurement measurement,+,measurement
		measurement_mult measurement measurement,*,measurement
		measurement_inverse measurement measurement,^-1
		measurement_fromString measurement string,toMeasurement
		measurement_le boolean measurement,<=,measurement
		measurement_toNumber number measurement,toNumber
		measurement_unit measurement measurement,unit,unitOfMeasurement
		measurement_naturalConstant measurement naturalConstant,c
		measurement_naturalConstant measurement naturalConstant,e
		measurement_naturalConstant measurement naturalConstant,h
		measurement_naturalConstant measurement naturalConstant,NA
		measurement_naturalConstant measurement naturalConstant,k
		measurement_naturalConstant measurement naturalConstant,g
		measurement_changeValue . measurement,:=,measurement;
	));
	push (@lambda::master::functions1, qw (
		measurement_new1 measurement new,#measurement,number,unitOfMeasurement_new1;
	));
	$lambda::error::msgE{"measurement_01"} = "Wert vom Typ measurement ist nicht dimensionslos. Dimension: &&1";
	$lambda::error::msgE{"measurement_02"} = "Einheiten von &&1 und &&2 sund nicht kompatibel!";
	$lambda::error::msgE{"measurement_03"} = "Naturkonstante &&1 nicht definiert.";
package lambda::base;
	sub isMeasurement {}
package lambda::clsMeasurement;
	use vars ('@ISA');
	@ISA = qw (lambda::clsNumber);
	sub new {lambda::classes::measurement->new (@_)}
	sub init {
		my $class = shift;
		$lambda::master->defProperty ($class, "unit", lambda::property->new ($lambda::master::unitOfMeasurement->new), "rw");
	}
package lambda::classes::measurement;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::number);
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift;
		my ($number, $unit, $scal) = @_;
		$self->{unit} = $unit || $lambda::master::unitOfMeasurement->new;
		$self->{scal} = $scal || 0;
		$self->measurementFromNumber ($number || $lambda::master::number->new);
		$self;
	}
	sub measurementFromNumber {
		my ($measurement, $number) = @_;
		return $measurement if $number->isEmpty;
		my $unit = $measurement->{unit};
		$number->plus ($unit->{z})->mult ($unit->{f})->copyTo ($measurement);
		$measurement;
	}
	sub check {
		my ($m1, $m2) = @_;
		my $u1 = $m1->{unit};
		my $u2 = $m2->{unit};
		$u1->signatur ne $u2->signatur ? lambda::error->new (43, $m1, $m2) : $u1;
	}
	sub compare {
		my ($p1, $p2) = @_;
		return 0 if $p1 eq $p2;
		return 1 if ! $p2->isMeasurement;
		my $u1 = $p1->{unit};
		my $u2 = $p2->{unit};
		return lambda::error->new (43, $p1, $p2) if $u1->signatur ne $u2->signatur;
		return 1 if lambda::classes::number::compare ($p1, $p2);
		$p1->{scal} + $u1->{n} <=> $p2->{scal} + $u2->{n};
	}
	sub plus {
		my ($p1, $p2) = @_;
		my $u = $p1->{unit};
		return lambda::error->new (43, $p1, $p2) if $u->signatur ne $p2->{unit}->signatur;
		my $scal = $p1->{scal};
		my $u2 = $p2->{unit};
		my $d = $scal - $p2->{scal} - $u->{n} + $u2->{n};
		my $n = $lambda::master::number->new ($p2->{num}, $p2->{den});
		if ($d > 0) {
			lambda::classes::number::multInteger ($n, 10 ** $d);
		} elsif ($d < 0) {
			lambda::classes::number::divInteger ($n, 10 ** (- $d));
		}
		$p2->{scal} = $scal;
		my $m = $lambda::master::number->new ($p1->{num}, $p1->{den})->plus ($n);
		$u->toSI if $u->{notSI};
		$lambda::master::measurement->new ($m, $u, $scal);
	}
	sub mult {
		my ($p1, $p2) = @_;
		my $u1 = $p1->{unit};
		my $u2 = $p2->{unit};
		$lambda::master::measurement->new (lambda::classes::number::mult ($p1, $p2), $u1->mult ($u2), $p1->{scal} + $p2->{scal});
	}
	sub zahl {
		my $self = shift;
		my $unit = $self->{unit};
		my $number = $lambda::master::number->new ($self->{num}, $self->{den});
		my $exp = $self->{scal} + $unit->{n};
		if ($unit->{name}) {
			$number = $number->divi ($unit->{f})->minus ($unit->{z}) if $unit->{notSI};
			$exp -= $unit->{n};
		}
		$number->mult ($lambda::ten->multiply ($lambda::master::number->newFromString ($exp)));
	}
	sub string {
		my $self = shift;
		my $s = $self->zahl->string;
		my $u = $self->{unit}->string;
		$u =~ s /^\[|\]$//g;
		$u ? "$s $u" : $s;
	}
	sub copyTo {
		my ($old, $new) = @_;
		lambda::classes::number::copyTo ($old, $new);
		$new->{scal} = $old->{scal};
		$new->{unit} = $old->{unit};
	}
	sub isMeasurement {1}
package lambda::init;
	sub measurement_new {
		my ($bracket, $number, $symbol) = shift->firsts (3);
		my $unit;
		if ($symbol) {
			$unit = $lambda::master::unitOfMeasurement->new ($symbol->{value}->{value});
			return $lambda::error if $lambda::error;
			$symbol->erase;
		} else {
			$unit = $lambda::master::unitOfMeasurement->new;
		}
		$number->newAtomAfter->setValue ($unit);
		lambda::property->new ($lambda::master::measurement->new ($number->{return}->{value}, $unit));
	}
	sub measurement_toNumber {
		my $u = shift->first->{return}->{value}->{unit};
		$u->isDimensionless ?
			lambda::property->new ($lambda::master::number->new) : lambda::error->new ("measurement_01", $u);
	}
	sub measurement_naturalConstant {
		my $atom = shift;
		$atom->first->erase;
		my $s = $atom->first->detach->{value};
		my $u;
		my $n;
		my $scal = 0;
		if ($s eq "c") {
			$u = $lambda::master::unitOfMeasurement->new ("ms-1");
			$n = lambda::atom::valueFromString ("2.99792458");
			$scal = 8;
		} elsif ($s eq "e") {
			$u = $lambda::master::unitOfMeasurement->new ("C");
			$n = lambda::atom::valueFromString ("1.602176634");
			$scal = -19;
		} elsif ($s eq "k") {
			$u = $lambda::master::unitOfMeasurement->new ("JK-1");
			$n = lambda::atom::valueFromString ("1.380649");
			$scal = -23;
		} elsif ($s eq "h") {
			$u = $lambda::master::unitOfMeasurement->new ("Js");
			$n = lambda::atom::valueFromString ("6.62607015");
			$scal = -34;
		} elsif ($s eq "NA") {
			$u = $lambda::master::unitOfMeasurement->new ("mol-1");
			$n = lambda::atom::valueFromString ("6.02214086");
			$scal = 23;
		} elsif ($s eq "g") {
			$u = $lambda::master::unitOfMeasurement->new ("ms-2");
			$n = lambda::atom::valueFromString ("9.80665");
		} else {
			return lambda::error->new ("measurement_03", $s);
		}
		my $m = $atom->{value} = $lambda::master::measurement->new ($n, $u, $scal);
		$m->{constant} = 1;
		$atom->{return} = lambda::property->new ($m);
	}
package lambda::command;
	sub measurement_plus {$_[1]->plus ($_[3])}
	sub measurement_mult {$_[1]->mult ($_[3])}
	sub measurement_multNumber {
		my ($atom, $n, $op, $m) = @_;
		$n->isMeasurement ?
			$lambda::master::measurement->new ($m->mult ($n), $m->{unit}, $m->{scal}):
			$lambda::master::measurement->new ($n->mult ($m), $n->{unit}, $n->{scal});
	}
	sub measurement_new {
		my ($atom, $op, $number, $unit) = @_;
		$lambda::master::measurement->new ($number, $unit);
	}
	sub measurement_le {$_[1]->compare ($_[3]) > 0 ? $lambda::false : $lambda::true}
	sub measurement_multNumber1 {
		my ($atom, $m, $op, $n) = @_;
		$lambda::master::measurement->new ($n->mult ($m), $m->{unit}, $m->{scal});
	}
	sub measurement_multNumber2 {
		my ($atom, $n, $op, $m) = @_;
		$lambda::master::measurement->new ($n->mult ($m), $m->{unit}, $m->{scal});
	}
	sub measurement_toNumber {
		my ($atom, $self) = @_;
		$lambda::master::number->new ($self->{num}, $self->{den});
	}
	sub measurement_fromString {
		my ($atom, $string) = @_;
		my $m = $string->{value};
		my $u = "";
		$m =~ s/^\s+|\s+$//g;
		if ($m =~ /^(.*?)\s+(.*)$/) {
			$m = $1;
			$u = $2;
		}
		my $unit = lambda::classes::unitOfMeasurement->new ($u);
		return if $lambda::error;
		my $number = lambda::atom::valueFromString ($m);
		return lambda::error->new (7, $m, $lambda::master::number) if ! $number->isNumber;
		$lambda::master::measurement->new ($number, $unit);
	}
	sub measurement_unit {
		my ($atom, $m, $op, $unitNew) = @_;
		my $unitOld = $m->{unit};
		return lambda::error->new ("measurement_02", $unitOld, $unitNew) if ! $unitOld->eq ($unitNew);
		$m->{scal} = $m->{scal} + $unitOld->{n} - $unitNew->{n};
		$m->{unit} = $unitNew;
		$m;
	}
	sub measurement_naturalConstant {
		shift->{return}->{value};
	}
	sub measurement_inverse {
		my ($atom, $self) = @_;
		my $self1 = $self->inverse;
		$self1->{unit} = $self->{unit}->inverse;
		$self1;
	}
	sub measurement_changeValue {
		my ($atom, $v1, $op, $v2)  = @_;
		$v1->{unit}->eq ($v2->{unit}) ? value_changeValue (@_) : lambda::error->new ("measurement_02", $v1, $v2);
	}
package lambda;
	push (@lambda::master::functions, qw (
		boolean_not boolean not,boolean#;boolean#,not;!,boolean#;boolean#,!
		boolean_ifCommand . if,boolean#,@*
		boolean_ifCommandElse . if,boolean#,@*,else,@*
		boolean_ifBlock . if,boolean#,@block,(boolean#,@block);if,boolean#,@block,(boolean#,@block),@block
		boolean_ifValue . if,boolean#,value,(boolean#,value),value
		boolean_or boolean boolean#,(|,boolean#);boolean#,(or,boolean#)
		boolean_and boolean boolean#,(&,boolean#);boolean#,(and,boolean#)
		boolean_while . while,list,@block
	));
package lambda::base;
	sub isBoolean {}
package lambda::clsBoolean;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
	sub new {lambda::classes::boolean->new (@_)}
package lambda::classes::boolean;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub isBoolean {1}
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift;
		$self->{value} = shift;
		$self;
	}
	sub isTrue {shift->{value}}
	sub isFalse {!shift->{value}}
	sub string {shift->{value} ? "true" : "false"}
	sub compare {
		my ($a, $b) = @_;
		return 1 if ! $b->isBoolean;
		return $b->{value} ? 0 : -1 if $a->{value};
		$b->{value} ? -1 : 0;
	}
package lambda::init;
	sub boolean_ifCommand {
		my $atom = shift;
		$atom->newAtomAfter->appendAtoms ($atom->firsts (2), "dBlock")->last->appendAtoms ($atom);
		$lambda::undefined;
	}
	sub boolean_ifCommandElse {
		my $atom = shift;
		my $block = $atom->newAtomAfter->appendAtoms ($atom->firsts (2), "dBlock dBlock")->last;
		$block->appendAtoms ("list");
		my $blockList = $block->first;
		my $list = $atom->{value};
		while (1) {
			my $last = $list->{last};
			my $symbol = $last->{return};
			if ($symbol->isSymbol ("else")) {
				$last->erase;
				$block->{before}->appendAtoms ($atom);
				return $lambda::undefined;
			} else {
				$blockList->insertAsFirst ($last->{value}, $symbol);
				$last->erase;
			}
		}
	}
	sub boolean_ifValue {
		my $atom = shift;
		my $if = $atom->first->{value};
		my $newAtom = $atom->newAtomAfter;
		if ($atom->fifth) {
			$newAtom->appendAtoms ($atom->firsts (3));
			$newAtom->appendAtoms ($atom);
			$newAtom->last->insertAsFirst ($if, $if);
			$newAtom->last->fixAnalyze ("boolean_ifValue");
			return $lambda::error ? undef : $newAtom->fixAnalyze ("boolean_ifValue");
		}
		$lambda::microScript = 1;
		my $block = $newAtom->{value} = lambda::commandBlock->new;
		$newAtom->appendAtoms ($atom);
		$atom->appendAtoms ("dBlock dBlock");
		$atom->last->appendAtoms ("list");
		$atom->last->{before}->appendAtoms ("list");
		$newAtom->appendAtoms ("list");
		my $value1 = $atom->third;
		my $value2 = $value1->{next};
		my $class1 = $value1->{return}->{class};
		my $class2 = $value2->{return}->{class};
		my $class = $class1->ancestor ($class2);
		return lambda::error->new (73, $class1, $class2) if $class->isUndefined;
		my $temp = lambda::symbol->new;
		my $property = $newAtom->{return} = $newAtom->defSymbol ($temp, lambda::property->new ($class));
		$block = $value2->{next};
		my $ff = $block->first;
		$ff->appendAtoms ($temp, ":=", $value1);
		$ff->first->{return} = $property;
		$block->{return} = $block->first->fixAnalyze ("value_changeValue");
		return if $lambda::error;
		$block = $block->{next};
		$ff = $block->first;
		$ff->appendAtoms ($temp, ":=", $value2);
		$ff->first->{return} = $property;
		$block->{return} = $block->first->fixAnalyze ("value_changeValue");
		return if $lambda::error;
		my $return = $atom->fixAnalyze ("boolean_ifBlock");
		return if $lambda::error;
		my $comm2 = $newAtom->last;
		$comm2->insertValues ($temp);
		$comm2->first->{return} = $property;
		undef $lambda::microScript;
		$lambda::error ? undef : $comm2->fixAnalyze ("data_value");
	}
	sub boolean_ifBlock {
		my $atom = shift;
		my ($if, $bool1, $block1, $bool2, $block2) = $atom->firsts (5);
		$block1->analyze;
		return if $lambda::error;
		return $lambda::undefined if ! $bool2;
		if ($block2) {
			my $newAtom = $atom->newAtomAfter;
			$newAtom->appendAtoms ("if", $bool1, $block1, "dBlock");
			my $block = $newAtom->last->appendAtoms ($atom);
			$block->first->fixAnalyze ("boolean_ifBlock");
		} else {
			$bool2->analyze;
		}
		$lambda::undefined;
	}
	sub boolean_while {
		my $atom = shift;
		my ($first, $second, $third) = $atom->firsts (3);
		$first->erase;
		$atom->appendAtoms ("repeat", "dBlock");
		my $doIf = $atom->{value}->{last}->appendAtoms ("list")->{value}->{first};
		$doIf->appendAtoms ("if", $second, $third, "dBlock");
		my $quit = $doIf->{value}->{last};
		$quit->appendAtoms ("list");
		$quit->first->appendAtoms ("quit");
		$doIf->second->{return} = $second->{return};
		delete $doIf->second->{value}->{quote};
		$atom->analyze;
	}
package lambda::command;
	sub boolean_and {
		my $atom = shift;
		do {
			my $value = shift;
			return $lambda::false if $value->isFalse;
			shift;
		} until (!@_);
		$lambda::true;
	}
	sub boolean_or {
		my $atom = shift;
		do {
			my $value = shift;
			return $lambda::true if $value->isTrue;
			shift;
		} until (!@_);
		$lambda::false;
	}
	sub boolean_not {
		my ($atom, $s, $b) = @_;
		$b = $s if $s->isBoolean;
		$b->isTrue ? $lambda::false : $lambda::true;
	}
	sub boolean_ifBlock {
		my ($atom, $op, $boolean) = @_;
		$atom->first->erase;
		$atom->first->erase;
		my ($b1, $b2) = $atom->firsts (2);
		if ($boolean->isFalse) {
			$b1->erase;
			return $lambda::undefined if ! $b2;
		} elsif ($b2) {
			$b2->erase;
		}
		$atom->setValue ($atom->first->detach)->toCommandBlock;
		$lambda::pureEmpty;
	}
package lambda;
	push (@lambda::master::functions, qw (
	file_import . import,file;file
));
package lambda::base;
	sub isClsFile {}
	sub isFile {}
package lambda::clsFile;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
	sub new {lambda::classes::file->new (@_)}
package lambda::classes::file;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift;
		$self->{value} = shift || "";
		$self;
	}
	sub isFile {1}
	sub string {shift->{value}}
package lambda::init;
	sub file_import {
		my $atom = shift;
		my ($first, $second) = $atom->firsts (2);
		my $file = $first->{return}->isSymbol ? $second->{value}->{value} : $first->{value}->{value};
		open (IN, '<' . $file) or return lambda::error->new (6, $file);
		my @datei = <IN>;
		close IN;
		my $script = "";
		$lambda::script = lambda::prepare (@datei) . " $lambda::script";
		$atom->erase;
		$lambda::undefined;
	}
package lambda;
	push (@lambda::master::functions, qw (
		moment_now moment now
		moment_today moment today;day,moment
		moment_easter moment easter;moment,easter
		moment_tomorrow moment tomorrow
		moment_yesterday moment yesterday
		moment_second moment second;second,moment
		moment_minute moment minute;minute,moment
		moment_hour moment hour;hour,moment
		moment_week moment week;week,moment
		moment_month moment month;month,moment
		moment_year moment year;year,momemt
		moment_part number moment,millisecond;moment,second;moment,minute;moment,hour;moment,day;moment,weekday;moment,week;moment,month;moment,year
		moment_eq boolean moment,=,moment
		moment_ne boolean moment,!=,moment
		moment_le boolean moment#,<=,moment#
		moment_lt boolean <,moment
		moment_gt boolean >,moment
		moment_minus1 timespan moment#,-,moment#
		moment_minus moment moment#,-,timespan
		moment_plus moment moment#,(+),timespan#;timespan#,(+),moment#
		moment_yesterday1 moment timespan,yesterday
		moment_today1 moment timespan,today
		moment_tomorrow1 moment timespan,tomorrow
		moment_timespan moment [,timespan,]
	));
package lambda::base;
	sub isMoment {}
package lambda::clsMoment;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
	sub new {lambda::classes::moment->new (@_)}
package lambda::classes::moment;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub isMoment {1}
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift;
		my $time = shift;
		$time = Time::HiRes::gettimeofday () if ! $time;
		$self->{value} = $time;
		$self;
	}
	sub string {
		my $self = shift->{value};
		my ($sec, $min, $hour, $mday, $mon, $year) = localtime ($self);
		my $d = sprintf "%02d.%02d.%04d %02d:%02d,%02d", $mday, $mon + 1, $year + 1900, $hour, $min, $sec;
		$d .= sprintf ".%03d", 1000 * ($self - int ($self));
	}
	sub compare {
		my ($a, $b) = @_;
		return 1 if ! $b->isMoment;
		$a->{value} <=> $b->{value};
	}
	sub plusTimespan {
		my ($moment, $timespan) = @_;
		my $result = $moment->copy;
		if ($timespan->{months}) {
			my ($sec, $min, $hour, $mday, $mon, $year) = localtime ($moment->{value});
			$mon += $timespan->{months};
			my $mon1 = $mon + 1;
			my $r = $mon1 % 12;
			my $year1 = $year + ($mon1 - $r) / 12;
			my $lDay = Time::Local::timelocal (0, 0, 0, 1, $r, $year1) - lambda::daySeconds;
			my ($sec1, $min1, $hour1, $mday1, $mon2, $year2) = localtime ($lDay);
			$mday = $mday1 if $mday > $mday1;
			$r = $mon % 12;
			$year += ($mon - $r) / 12;
			$result->{value} = Time::Local::timelocal ($sec, $min, $hour, $mday, $r, $year);
		}
		$result->{value} += $timespan->{seconds};
		$result;
	}
package lambda::init;
	sub moment_timespan {
		my $atom = shift;
		$atom->microScript ("'#1 := (today + &1); if (now <= #1) #1 (#1 + 24:00)", $atom->second);
	}
package lambda::command;
	sub moment_eq {$_[1]->{value} == $_[3]->{value} ? $lambda::true : $lambda::false}
	sub moment_ne {$_[1]->{value} != $_[3]->{value} ? $lambda::true : $lambda::false}
	sub moment_le {$_[1]->{value} <= $_[3]->{value} ? $lambda::true : $lambda::false}
	sub moment_now {shift; $lambda::master::moment->new}
	sub moment_second {
		my ($atom, $op, $moment) = @_;
		$moment = $lambda::master::moment->new if ! $moment;
		$moment->{value} = int ($moment->{value});
		$moment;
	}
	sub moment_minute {
		my ($atom, $op, $moment) = @_;
		$moment = $lambda::master::moment->new if ! $moment;
		my ($sec, $min, $hour, $mday, $mon, $year) = localtime ($moment->{value});
		$moment->{value} = Time::Local::timelocal(0, $min, $hour, $mday, $mon, $year);
		$moment;
	}
	sub moment_hour {
		my ($atom, $op, $moment) = @_;
		$moment = $lambda::master::moment->new if ! $moment;
		my ($sec, $min, $hour, $mday, $mon, $year) = localtime ($moment->{value});
		$moment->{value} = Time::Local::timelocal(0, 0, $hour, $mday, $mon, $year);
		$moment;
	}
	sub moment_tomorrow {
		my ($atom, $op, $timespan) = @_;
		my $day = moment_today ($atom, $op, $lambda::master::moment->new (Time::HiRes::gettimeofday () + lambda::daySeconds));
		$timespan ? momentPlus ($atom, $day, $timespan) : $day;
	}
	sub moment_yesterday {
		my ($atom, $op, $timespan) = @_;
		my $day = moment_today ($atom, $op, $lambda::master::moment->new (Time::HiRes::gettimeofday () - lambda::daySeconds));
		$timespan ? momentPlus ($atom, $day, $timespan) : $day;
	}
	sub moment_today {
		my ($atom, $op, $moment) = @_;
		$moment = $lambda::master::moment->new if ! $moment;
		my ($sec, $min, $hour, $mday, $mon, $year) = localtime ($moment->{value});
		$lambda::master::moment->new (Time::Local::timelocal(0, 0, 0, $mday, $mon, $year));
	}
	sub moment_yesterday1 {
		my ($atom, $timespan) = @_;
		moment_plus ($atom, moment_yesterday (), $timespan);
	}
	sub moment_today1 {
		my ($atom, $timespan) = @_;
		moment_plus ($atom, moment_today (), $timespan);
	}
	sub moment_tomorrow1 {
		my ($atom, $timespan) = @_;
		moment_plus ($atom, moment_tomorrow (), $timespan);
	}
	sub moment_week {
		my ($atom, $op, $moment) = @_;
		$moment = $lambda::master::moment->new if ! $moment;
		my ($sec, $min, $hour, $mday, $mon, $year, $wday) = localtime ($moment->{value});
		my $offset = $wday ? (--$wday * lambda::daySeconds) : 6 * lambda::daySeconds;
		$moment->{value} = Time::Local::timelocal(0, 0, 0, $mday, $mon, $year) - $offset;
		$moment;
	}
	sub moment_month {
		my ($atom, $op, $moment) = @_;
		$moment = $lambda::master::moment->new if ! $moment;
		my ($sec, $min, $hour, $mday, $mon, $year) = localtime ($moment->{value});
		$moment->{value} = Time::Local::timelocal(0, 0, 0, 1, $mon, $year);
		$moment;
	}
	sub moment_year {
		my ($atom, $op, $moment) = @_;
		$moment = $lambda::master::moment->new if ! $moment;
		my ($sec, $min, $hour, $mday, $mon, $year) = localtime ($moment->{value});
		$moment->{value} = Time::Local::timelocal(0, 0, 0, 1, 0, $year);
		$moment;
	}
	sub moment_easter {
		my ($atom, $moment, $op) = @_;
		$moment = $lambda::master::moment->new if ! $op;
		my ($sec, $min, $hour, $mday, $mon, $year) = localtime ($moment->{value});
		my $X = 1900 + $year;
		my $K = int ($X / 100);
		my $S = 2 - int ((3 * $K + 3) / 4);
		my $M = 17 - $S - int ((8 * $K + 13) / 25);
		my $A = $X % 19;
		my $D = (19 * $A + $M) % 30;
		my $R = int (($D + int ($A / 11)) / 29);
		my $G = 21 + $D - $R;
		my $Z = 7 - ($X + int ($X / 4) + $S) % 7;
		my $E = 7 - ($G - $Z) % 7;
		my $O = $G + $E;
		$mon = 2;
		if ($O > 31) {$mon = 3; $O = $O - 31}
		$lambda::master::moment->new (Time::Local::timelocal(0, 0, 0, $O, $mon, $year));
	}
	sub moment_part {
		my ($atom, $moment, $part) = @_;
		my $T = $moment->{value};
		my $name = $part->{value};
		if ($name eq "millisecond") {return $lambda::master::number->newFromString (sprintf "%03d", 1000 * ($T - int ($T)))};
		my ($sec, $min, $hour, $mday, $mon, $year, $wd, $yd) = localtime ($T);
		if ($name eq "second") {return $lambda::master::number->newFromString ($sec)};
		if ($name eq "minute") {return $lambda::master::number->newFromString ($min)};
		if ($name eq "hour") {return $lambda::master::number->newFromString ($hour)};
		if ($name eq "day") {return $lambda::master::number->newFromString ($mday)};
		if ($name eq "week") {return $lambda::master::number->newFromString (1 + int ($yd / 7))};
		if ($name eq "weekday") {return $lambda::master::number->newFromString ($wd ? $wd : 7)};
		if ($name eq "month") {return $lambda::master::number->newFromString (++$mon)};
		if ($name eq "year") {return $lambda::master::number->newFromString ($year + 1900)};
	}
	sub moment_lt {Time::HiRes::gettimeofday < $_[2]->{value} ? $lambda::true : $lambda::false}
	sub moment_gt {Time::HiRes::gettimeofday > $_[2]->{value} ? $lambda::true : $lambda::false}
	sub moment_minus1 {
		my ($atom, $moment1, $op, $moment2) = @_;
		$lambda::master::timespan->new ($moment1->{value} - $moment2->{value});
	}
	sub moment_plus {
		my ($atom, $moment, $op, $timespan) = @_;
		$timespan = $op if ! $op->isSymbol;
		$moment->isTimespan ? lambda::classes::moment::plusTimespan ($timespan, $moment) : lambda::classes::moment::plusTimespan ($moment, $timespan)
	}
	sub moment_minus {
		my ($atom, $self, $op, $timespan) = @_;
		moment_plus ($atom, $self, $lambda::master::timespan->new (-$timespan->{seconds}, -$timespan->{months}));
	}
	sub _moment_nextLaterMoment {
		my ($atom, $startTime, $timespan) = @_;
		return lambda::error->new (59, $timespan) if $timespan->{months} < 0 || $timespan->{seconds} < 0;
		return lambda::error->new (59, $timespan) if $timespan->{months} > 0 && $timespan->{seconds} > 0;
		my $t = Time::HiRes::gettimeofday;
		if ($startTime->{value} < $t) {
			if ($timespan->{seconds} > 0) {
				my $diff = $t - $startTime->{value};
				my $step = $timespan->{seconds};
				$startTime->{value} += (1 + int ($diff / $step)) * $step;
			} else {
				my ($sec0, $min0, $hour0, $mday0, $mon0, $year0) = localtime ($startTime->{value});
				my ($sec1, $min1, $hour1, $mday1, $mon1, $year1) = localtime ($t);
				my $diff = 12 * ($year1 - $year0) + $mon1 - $mon0;
				my $step = $timespan->{months};
				my $m = int ($diff / $step) * $step;
				my $y = int ($m / 12);
				$m = $m - 12 * $y + $mon0;
				if ($m > 11) {$m -= 12; $y++}
				$startTime->{value} = Time::Local::timelocal($sec0, $min0, $hour0, $mday0, $m, $year0 + $y);
				$startTime->{value} = moment_plus ($atom, $startTime, $timespan) if $startTime->{value} < $t;
			}
		}
		return $lambda::undefined;
	}
package lambda;
	push (@lambda::master::functions, qw (
		stack_shuffle . stack,shuffle
		stack_add . stack,<<,value,(value);value,(value),>>,stack;value,(value),>>,stack,<<,value,(value)
		stack_count1 number stack,count
		stack_count2 number count,stack
		stack_toBoolean boolean stack,toBoolean
		stack_forEach . forEach,stack#,@symbol,@block;forEach,stack#,value,@block
		stack_in boolean value,in,stack
		stack_getBottom . <,stack
		stack_getTop . stack,>
		stack_removeBottom . <<,stack
		stack_removeTop . stack,>>
	));
package lambda::base;
	sub isClsStack {}
	sub isStack {}
package lambda::clsValue;
	sub isClsStack {shift->isASubclass ($lambda::master::stack)}
package lambda::value;
	sub isStack {shift->{class}->isClsStack}
package lambda::clsStack;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
	sub new {lambda::classes::stack->new (@_)}
	sub isClsStack {1}
	sub init {
		my $class = shift;
		$lambda::master->defProperty ($class, "of", lambda::property->new ($lambda::master::class, $lambda::master::value), "rW");
	}
package lambda::classes::stack;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift;
		$self->initialize;
	}
	sub initialize {
		my $self = shift;
		my @s = ();
		$self->{value} = \@s;
		$self->{pointer} = 0;
		$self;
	}
	sub isStack {1}
	sub string {
		my $stack = shift;
		"(" . $stack->property ("of")->{value}->string . ":" . join (",", map {$_->{value}->string} @{$stack->{value}}) . ")"
	}
	sub compare {
		my ($p1, $p2) = @_;
		return 0 if $p1 eq $p2;
		return 1 if ! $p2->isStack || $p1->property ("of")->{value}->qName ne $p2->property ("of")->{value}->qName;
		$p1->{value} eq $p2->{value} ? 0 : 1;
	}
	sub copyTo {
		my ($from, $to) = @_;
		my @array = @{$from->{value}};
		$to->{value} = \@array;
	}
package lambda::init;
	sub stack_shuffle {shift->first->analyze->copy}
	sub stack_add {
		my $atom = shift;
		my ($first, $second, $third) = $atom->firsts (3);
		my $stackAtom;
		while ($second) {
			if ($second->{value}->isSymbol (">>")) {
				$stackAtom = $third;
				last;
			} elsif ($second->{value}->isSymbol ("<<")) {
				$stackAtom = $first;
				last;
			}
			$first = $second;
			$second = $third;
			$third = $third->{next};
		}
		return $lambda::pureEmpty if ! $stackAtom;
		my $property = $stackAtom->{return};
		my $dataClass = $property->{value}->property ("of")->{value};
		my $next = $atom->first;
		while ($next) {
			return $lambda::pureEmpty if ($next ne $stackAtom) && ! $next->{value}->isSymbol (">>", "<<") && ! $next->{return}->{class}->isASubclass ($dataClass);
			$next = $next->{next};
		}
		$first = $stackAtom->{before};
		$third = $stackAtom->{next};
		if ($first && $third && $first->{value}->isSymbol (">>") && $third->{value}->isSymbol ("<<")) {
			my $newAtom = $stackAtom->newAtomAfter;
			$next = $atom->first;
			while (1) {
				my $last = $next eq $stackAtom;
				my $next1 = $next->{next};
				$newAtom->appendAtoms ($next);
				$next = $next1;
				last if $last;
			}
			$newAtom->fixAnalyze ("stack_add", $property);
		}
		$property;
	}
	sub stack_in {
		my $atom = shift;
		my ($value, $symbol, $stack) = $atom->firsts (3);
		my $property = $stack->analyze;
		return if $lambda::error;
		my $dataClass = $property->{value}->property ("of")->{value};
		$property = $value->analyze;
		return if $lambda::error;
		my $valueClass = $property->{class};
		$valueClass->isASubclass ($dataClass) ? lambda::property->new ($lambda::master::boolean) : lambda::error->new (11, $dataClass, $valueClass);
	}
	sub stack_getTop {stack_removeTop (@_)}
	sub stack_getBottom {stack_removeBottom (@_)}
	sub stack_removeTop {
		my $property = shift->first->analyze;
		return if $lambda::error;
		lambda::property->new ($property->{value}->property ("of")->{value}, $lambda::pureEmpty);
	}
	sub stack_removeBottom {
		my $property = shift->second->analyze;
		return if $lambda::error;
		lambda::property->new ($property->{value}->property ("of")->{value}, $lambda::pureEmpty);
	}
	sub stack_forEach {
		my $atom = shift;
		my ($first, $second, $third, $fourth) = $atom->firsts (4);
		my $stack = $second->{return}->{value};
		my $class = $stack->property ("of")->{value};
		my $symbol = $third->{return};
		if ($symbol->isSymbol) {
			$third->{return} = $atom->defSymbol ($symbol, lambda::property->new ($class));
		} else {
			my $symbolClass = $symbol->{class};
			return lambda::error->new (11, $class, $symbolClass, undef, $atom->{value}) if ! $symbolClass->isASubclass ($class);
		}
		$fourth->analyze;
	}
package lambda::command;
	sub stack_shuffle {
		my ($atom, $array) = @_;
		my $newArray = $lambda::master::stack->new;
		$newArray->{properties}->{of} = $array->property ("of");
		my @newArray;
		rand () < 0.5 ? push @newArray, $_ : unshift @newArray, $_ foreach @{$array->{value}};
		$newArray->{value} = \@newArray;
		$newArray;
	}
	sub stack_add {
		my $atom = shift;
		my $case = $_[1]->isSymbol ("<<");
		my $first = $atom->first;
		my $last = $atom->last;
		my $stackProperty = $case ? $first->{return} : $last->{return};
		my $stack = $stackProperty->{value};
		$stack = $stackProperty->{value} = $stackProperty->{class}->new if $stack->isEmpty;
		my @array = @{$stack->{value}};
		if ($case) {
			$first = $first->{next};
			push @array, $first->{return} while $first = $first->{next};
		} else {
			$first = $last->{before};
			unshift @array, $first->{return} while $first = $first->{before};
		}
		$stack->{value} = \@array;
		$atom->lambda->putChangedProperty ($stackProperty);
		delete $stack->{constant}; #?
		$stack;
	}
	sub stack_count1 {shift; $lambda::master::number->newFromString (scalar @{shift->{value}})}
	sub stack_count2 {shift; shift; $lambda::master::number->newFromString (scalar @{shift->{value}})}
	sub stack_toBoolean {scalar @{$_[1]->{value}} == 0 ? $lambda::false : $lambda::true}
	sub stack_forEach {
		my ($atom, $op, $stack, $data, $block) = @_;
		my $second = $atom->second;
		if (! $atom->{notFirstLoop}) {
			$atom->{notFirstLoop} = 1;
			$stack->{pointer} = 0;
			$second->setValue ($stack);
		} else {
			$stack->{pointer}++;
		}
		my $property = @{$stack->{value}}[$stack->{pointer}];
		return $lambda::undefined if ! $property;
		my $foreach = $atom->newAtomBefore;
		$foreach->{quit} = 1;
		my %newProperties = ();
		$foreach->setValue ($block->copy->toCommandBlock);
		$foreach->{return} = $lambda::undefined;
		$atom->third->{return}->changeValue ($property->{value}, $atom->{root});
		$lambda::pureEmpty;
	}
	sub stack_in {
		my ($atom, $value, $symbol, $stack) = @_;
		my @array = @{$stack->{value}};
		foreach (@{$stack->{value}}) {
			return $lambda::true if ! $_->{value}->compare ($value);
		}
		$lambda::false;
	}
	sub stack_getBottom {
		my ($atom, $op, $stack) = @_;
		my @array = @{$stack->{value}};
		return lambda::error->new (51) if !@array;
		my $property = $array [0];
		$property->{value};
	}
	sub stack_getTop {
		my ($atom, $stack) = @_;
		my @array = @{$stack->{value}};
		return lambda::error->new (51) if !@array;
		my $property = $array [-1];
		$property->{value};
	}
	sub stack_removeTop {
		my ($atom, $stack) = @_;
		my @array = @{$stack->{value}};
		return lambda::error->new (51) if !@array;
		my $property = shift @array;
		$stack->{value} = \@array;
		$property->{value};
	}
	sub stack_removeBottom {
		my ($atom, $op, $stack) = @_;
		my @array = @{$stack->{value}};
		return lambda::error->new (51) if !@array;
		my $property = pop @array;
		$stack->{value} = \@array;
		$property->{value};
	}
package lambda;
	no warnings 'qw';
	push (@lambda::master::functions, qw (
		collection_getElement . [,collection#,@symbol,];[,collection#,word,]
		collection_toString . collection,toString
		collection_delElement . delete,collection#,@symbol;delete,collection#,word
		collection_count number collection#,count;count,collection#
		collection_toBoolean boolean collection,toBoolean
		collection_keys . collection,keys;keys,collection
		collection_existKey boolean collection,exist,word@symbol
		collection_notExistKey boolean collection,notExist,word@symbol
		collection_setDefault . collection,default,value
	));
	$lambda::error::msgE{"collection_01"} = "Die Eigenschaft 'of' kann nur bei der Definition festgelegt werden.";
package lambda::clsCollection;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
	sub new {lambda::classes::collection->new (@_)}
	sub init {
		my $collection = shift;
		$lambda::master->defProperty ($collection, "of", lambda::property->new ($lambda::master::class, $lambda::master::value));
		$lambda::master->defProperty ($collection, "default", lambda::property->new ($lambda::master::value));
	}
package lambda::classes::collection;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift;
		my %s = ();
		$self->{value} = \%s;
		$self;
	}
	sub string {
		my $self = shift;
		my %value = %{$self->{value}};
		my @array = ();
		foreach (sort keys %value) {
			my $value = $value{$_}->{value};
			push @array, $_ . "=>" . $value->string;
		}
		"{" . $self->property ("of")->{value}->{name}. "|" . join (", ", @array) ."}";
	}
	sub putElement {
		my ($self, $name, $element, $atom) = @_;
		my $array = $self->{value};
		my $property = $array->{$name};
		if ($property) {
			$property->changeValue ($element, $atom);
			if ($property->{changed}) {
				my $thread = $atom->isMaster ? $atom : $property->{value}->includedDevices ? $lambda::master : $atom->lambda;
				$thread->putChangedProperty ($property);
			}
		}
		$array->{$name} = lambda::property->new ($element);
		$lambda::undefined;
	}
	sub delElement {
		my ($self, $name, $atom) = @_;
		my $collection = $self->{value};
		my $property = $collection->{$name};
		if ($property) {
			delete $collection->{$name};
			$atom->lambda->putChangedProperty ($atom->second->{return});
		}
		$lambda::undefined;
	}
	sub copyTo {lambda::vector::copyTo (@_)}
package lambda::init;
	sub collection_setOf {
		lambda::error->new ("collection_01");
	}
	sub collection_setDefault {
		my ($collection, $symbol, $value) = shift->firsts (3);
		my $property = $collection->{return};
		my $class = $property->{value}->property ("of")->{value};
		my $classValue = $value->{return}->{class};
		$classValue->isASubclass ($class) ? $property : lambda::error->new (66, $classValue, $class);
	}
	sub collection_getElement {
		my $ofClass = shift->second->{return}->{value}->property ("of")->{value};
		lambda::property->new ($ofClass);
	}
	sub collection_keys {
		my $keys = $lambda::master::stack->new;
		$keys->modifyProperty ("of", $lambda::master::word);
		shift->{return} = lambda::property->new ($keys);
	}
	sub collection_toString {lambda::property->new ($lambda::master::string)}
package lambda::command;
	sub collection_setDefault {
		my ($atom, $collection, $symbol, $value) = @_;
		$collection->{properties}->{$symbol->{value}} = lambda::property->new ($value);
		$lambda::undefined;
	}
	sub collection_getElement {
		my ($atom, $op1, $collection, $symbol, $op2) = @_;
		my $name = $symbol->{value};
		my $hash = $collection->{value};
		my $property = $hash->{$name};
		if (! $property) {
			$property = $hash->{$name} = $collection->property ("default")->copy;
			$property->{inArray} = $atom->second->{return};
		}
		$atom->{return} = $property;
		$property->{value};
	}
	sub collection_delElement {
		my ($atom, $op, $collection, $symbol) = @_;
		$collection->delElement ($symbol->{value}, $atom);
		$lambda::undefined;
	}
	sub collection_toBoolean {scalar keys %{$_[1]->{value}} == 0 ? $lambda::false : $lambda::true}
	sub collection_count {
		my ($atom, $collection, $op) = @_;
		$collection = $op if $collection->isSymbol;
		$lambda::master::number->newFromString (scalar keys %{$collection->{value}})
	}
	sub collection_toString {shift; $lambda::master::string->new (shift->string)}
	sub collection_keys {
		my ($atom, $collection, $op) = @_;
		$collection = $op if $collection->isSymbol;
		my $stack = $atom->{return}->{value};
		my @keys = ();
		push @keys, lambda::property->new ($lambda::master::word->new ($_)) foreach sort keys %{$collection->{value}};
		$stack->{value} = \@keys;
		$stack;
	}
	sub collection_existKey {
		my ($atom, $collection, $op, $symbol) = @_;
		exists $collection->{value}->{$symbol->{value}} ? $lambda::true : $lambda::false;
	}
	sub collection_notExistKey {
		my ($atom, $collection, $op, $symbol) = @_;
		exists $collection->{value}->{$symbol->{value}} ? $lambda::false : $lambda::true;
	}
package lambda;
	push (@lambda::master::functions, qw (
		vector_getElement . [,vector#,number#,]
		vector_toBoolean boolean vector,toBoolean
		vector_modifyDefault . vector#,default,value
	));
package lambda::clsVector;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
	sub new {lambda::vector->new (@_)}
	sub init {
		my $vector = shift;
		$lambda::master->defProperty ($vector, "dimension", lambda::property->new ($lambda::master::number, $lambda::master::number->new), "rw");
		$lambda::master->defProperty ($vector, "default", lambda::property->new (lambda::empty->new ($lambda::master::value)), "rw");
	}
package lambda::vector;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift->copy;
		my %s = ();
		$self->{value} = \%s;
		$self;
	}
	sub string {
		my $self = shift;
		my $n = $self->property ("dimension")->{value}->string;
		my %a = $self->{value} ? %{$self->{value}} : {};
		my $data = $self->property ("default");
		my @array = ();
		push @array, "$_=>" . $a{$_}->{value}->string foreach sort keys %a;
		"(1:$n|" . $data->{value}->string . "|" . join (",", @array) . ")";
	}
	sub copyTo {
		my ($from, $to) = @_;
		my %array1 = %{$from->{value}};
		my %array2 = ();
		$array2{$_} = $array1{$_} foreach keys %array1;
		$to->{value} = \%array2;
	}
package lambda::init;
	sub vector_modifyDefault {
		my $atom = shift;
		$atom->changeCommand ("value_modify");
		$atom->first->{return}->{value}->{class}->{properties}->{default} = $atom->third->{return};
	}
	sub vector_getElement {
		shift->second->{return}->{value}->property ("default")->copy;
	}
package lambda::command;
	sub vector_toBoolean {
		$_[1]->property ("dimension")->{value}->string ? $lambda::true : $lambda::false;
	}
	sub vector_getElement {
		my ($atom, $op1, $vector, $number, $op2) = @_;
		my $d = $vector->property ("dimension")->{value}->{num}->string;
		my $n = $number->{num}->string;
		return lambda::error->new (8, 1, $d, $number) if ! $number->isInteger || $n < 1 || $n > $d;
		my $array = $vector->{value};
		my $property = $array->{$n};
		if (! $property) {
			$property = $array->{$n} = $vector->property ("default")->copy;
			$property->{inArray} = $atom->second->{return};
		}
		$atom->{return} = $property;
		$property->{value};
	}
package lambda;
	push (@lambda::master::functions, qw (
		timespan_seconds timespan number,seconds
		timespan_minutes timespan number,minutes
		timespan_hours timespan number,hours
		timespan_days timespan number,days
		timespan_weeks timespan number,weeks
		timespan_months timespan number,months
		timespan_years timespan number,years
		timespan_minus timespan timespan,-,timespan
		timespan_plus timespan timespan,(+),timespan
		timespan_lt boolean [,.,timespan,]
		timespan_gt boolean [,timespan,.,]
		timespan_in boolean [,timespan,timespan,]
		timespan_repeatPeriodic0 . repeat,timespan,@block
		timespan_repeatPeriodic3 . repeat,number,@block
		timespan_repeatPeriodic6 . repeat,moment,@block
		timespan_repeatPeriodic1 . repeat,timespan,number,@block;repeat,number,timespan,@block
		timespan_repeatPeriodic2 . repeat,moment,number,@block;repeat,number,moment,@block
		timespan_repeatPeriodic4 . repeat,moment,timespan,@block;repeat,timespan,moment,@block
		timespan_repeatPeriodic5 . repeat,value,value,value,@block
		timespan_repeatPeriodic . repeat,moment,timespan,number,@block
	));
package lambda::base;
	sub isTimespan {}
package lambda::clsTimespan;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
	sub new {lambda::classes::timespan->new (@_)}
package lambda::classes::timespan;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub isTimespan {1}
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift;
		$self->{seconds} = shift || 0;
		$self->{months} = shift || 0;
		$self;
	}
	sub string {
		my $self = shift;
		my $v = $self->{months};
		my $string1 = $v ? "$v/" : "";
		my $sec0 = $self->{seconds};
		return "$v/0/0:0,0" if ! $sec0;
		my $sec = abs ($sec0);
		my $s = int ($sec);
		my $f = $sec - $s;
		my $ms = "";
		if ($f) {
			$ms = sprintf ("%.3f", $f);
			$ms =~ s/^0|0*$//g;
		}
		$v = int ($sec / lambda::daySeconds);
		my $string2 = $v ? "$v/" : "";
		my $h = $sec % lambda::daySeconds;
		$v = int ($h / lambda::hourSeconds);
		$h = $h % lambda::hourSeconds;
		$string2 .= "$v:" if $v || $string2;
		$v = int ($h / 60);
		$h = $h % 60;
		$string2 .= $v if $v || $string2;
		$string2 .= $h || ! $string2 ? ",$h" : ",0";
		$string2 = "-$string2" if $sec0 < 0;
		$string1 . $string2.$ms;
	}
	sub compare {
		my ($t1, $t2) = @_;
		return 1 if ! $t2->isTimespan;
		$t1->{seconds} <=> $t2->{seconds} || $t1->{months} <=> $t2->{months};
	}
	sub copyTo {
		my ($from, $to) = @_;
		$to->{seconds} = $from->{seconds};
		$to->{months} = $from->{months};
	}
	sub checkTimeOfDay {
		my $self = shift;
		$self->{months} != 0 || $self->{seconds} < 0 || $self->{seconds} > lambda::daySeconds ? lambda::error->new (58, $self) : $lambda::undefined;
	}
package lambda::init;
	sub timespan_repeatPeriodic0 {
		my $atom = shift;
		my $m = $atom->first->newAtomAfter;
		my $e = $m->{return} = lambda::property->new ($lambda::master::moment);
		$m->{value} = $e->{value};
		my $n = $atom->last->newAtomBefore;
		$e = $n->{return} = lambda::property->new ($lambda::master::number);
		$n->{value} = $e->{value};
		$atom->fixAnalyze ("timespan_repeatPeriodic");
	}
	sub timespan_repeatPeriodic1 {
		my $atom = shift;
		my $n = $atom->first->newAtomAfter;
		my $e = $n->{return} = lambda::property->new ($lambda::master::moment);
		$n->{value} = $e->{value};
		$atom->fixAnalyze ("timespan_repeatPeriodic");
	}
	sub timespan_repeatPeriodic2 {
		my $atom = shift;
		my $n = $atom->second->newAtomAfter;
		my $e = $n->{return} = lambda::property->new ($lambda::master::timespan);
		$n->{value} = $e->{value};
		$atom->fixAnalyze ("timespan_repeatPeriodic");
	}
	sub timespan_repeatPeriodic3 {
		my $atom = shift;
		my $n = $atom->first->newAtomAfter;
		my $e = $n->{return} = lambda::property->new ($lambda::master::timespan);
		$n->{value} = $e->{value};
		$n = $atom->first->newAtomAfter;
		$e = $n->{return} = lambda::property->new ($lambda::master::moment);
		$n->{value} = $e->{value};
		$atom->fixAnalyze ("timespan_repeatPeriodic");
	}
	sub timespan_repeatPeriodic4 {
		my $atom = shift;
		my $n = $atom->last->newAtomBefore;
		my $e = $n->{return} = lambda::property->new ($lambda::master::number);
		$n->{value} = $e->{value};
		$atom->fixAnalyze ("timespan_repeatPeriodic");
	}
	sub timespan_repeatPeriodic5 {
		my $atom = shift;
		my ($repeat, $m, $t, $n) = $atom->firsts (4);
		if (! $m->{return}->{class}->isASubclass ($lambda::master::moment)) {
			if ($t->{return}->{class}->isASubclass ($lambda::master::moment)) {
				 $m->swap ($t);
			} elsif ($n->{return}->{class}->isASubclass ($lambda::master::moment)) {
				 $m->swap ($n);
			} else {
				return $lambda::pureEmpty;
			}
		}
		($repeat, $m, $t, $n) = $atom->firsts (4);
		if (! $t->{return}->{class}->isASubclass ($lambda::master::timespan)) {
			if ($n->{return}->{class}->isASubclass ($lambda::master::timespan)) {
				$n->swap ($t);
			} else {
				return $lambda::pureEmpty;
			}
		}
		$atom->fourth->{return}->{class}->isASubclass ($lambda::master::number) ?
			$atom->fixAnalyze ("timespan_repeatPeriodic") : $lambda::pureEmpty;
	}
	sub timespan_repeatPeriodic6 {
		my $atom = shift;
		my $n = $atom->second->newAtomAfter;
		my $e = $n->{return} = lambda::property->new ($lambda::master::number);
		$n->{value} = $e->{value};
		$n = $atom->second->newAtomAfter;
		$e = $n->{return} = lambda::property->new ($lambda::master::timespan);
		$n->{value} = $e->{value};
		$atom->fixAnalyze ("timespan_repeatPeriodic");
	}
	sub timespan_repeatPeriodic {shift->last->analyze}
package lambda::command;
	sub timespan_seconds {my ($atom, $n) = @_; $lambda::master::timespan->new ($n->value)}
	sub timespan_minutes {my ($atom, $n) = @_; $lambda::master::timespan->new ($n->multInteger (60)->value)}
	sub timespan_hours {my ($atom, $n) = @_; $lambda::master::timespan->new ($n->multInteger (lambda::hourSeconds)->value)}
	sub timespan_days {my ($atom, $n) = @_; $lambda::master::timespan->new ($n->multInteger (lambda::daySeconds)->value)}
	sub timespan_weeks {my ($atom, $n) = @_; $lambda::master::timespan->new ($n->multInteger (lambda::daySeconds * 7)->value)}
	sub timespan_months {
		my ($atom, $n) = @_;
		$n->isInteger ? $lambda::master::timespan->new (0, $n->value) : lambda::error->new (4, $n);
	}
	sub timespan_years {
		my ($atom, $n) = @_;
		$n->isInteger ? $lambda::master::timespan->new (0, $n->multInteger (12)->value) : lambda::error->new (4, $n);
	}
	sub timespan_lt {
		my $atom = shift;
		Time::HiRes::gettimeofday () <= moment_plus ($atom, moment_today ($atom, shift), shift)->{value} ? $lambda::true : $lambda::false;
	}
	sub timespan_gt {my $atom = shift; Time::HiRes::gettimeofday () >= moment_plus ($atom, moment_today ($atom, shift), shift)->{value} ? $lambda::true : $lambda::false}
	sub _timespan_lt {
		my $atom = shift;
		Time::HiRes::gettimeofday () <= moment_plus ($atom, moment_today ($atom, shift), shift)->{value} ? $lambda::true : $lambda::false;
	}
	sub timespan_in {
		my ($atom, $op1, $t1, $t2, $op2) = @_;
		$t1->checkTimeOfDay;
		return if $lambda::error;
		$t2->checkTimeOfDay;
		return if $lambda::error;
		$b = timespan_gt ($atom, $op2, $t1);
		if ($t1->{seconds} < $t2->{seconds}) {
			return $b->isFalse ? $b : _timespan_lt ($atom, $op1, $t2);
		} else {
			return $b->isTrue ? $b : _timespan_lt ($atom, $op1, $t2);
		}
	}
	sub timespan_today {moment_plus (shift, moment_today, shift)}
	sub timespan_tomorrow {moment_plus (shift, moment_tomorrow, shift)}
	sub timespan_plus {
		my ($atom, $self, $op, $timespan) = @_;
		$timespan = $op if ! $op->isSymbol;
		$lambda::master::timespan->new ($self->{seconds} + $timespan->{seconds}, $self->{months} + $timespan->{months});
	}
	sub timespan_minus {
		my ($atom, $self, $op, $timespan) = @_;
		timespan_plus ($atom, $self, $lambda::master::timespan->new (-$timespan->{seconds}, -$timespan->{months}));
	}
	sub timespan_repeatPeriodic {
		my ($atom, $op, $startTime, $timespan, $number, $block) = @_;
		my $startAtom = $atom->second;
		my $now = Time::HiRes::gettimeofday ();
		return lambda::error->new (59, $timespan) if ! $timespan->isEmpty && ($timespan->{months} < 0 || $timespan->{seconds} < 0);
		my $n = $atom->{value}->{number};
		if (! $n) {
			$n = $atom->{value}->{number} = $number->copy;
			if (! $number->isEmpty) {
				return lambda::error->new (17, "Null", $number) if ! $number->isNotNegInteger;
				return $lambda::undefined if $n->{num}->isZero;
			}
			$startTime = $lambda::master::moment->new ($now) if $startTime->isEmpty;
			if ($startTime->{value} < $now && ! $timespan->isEmpty) {
				while (1) {
					$startTime = moment_plus ($atom, $startTime, $timespan);
					last if $now <= $startTime->{value};
					$n->isEmpty ? next : $n->{num}->subA (1);
					return $lambda::undefined if $n->{num}->isZero;
				}
			}
			$startAtom->setValue ($startTime);
			$atom->{value}->{number} = $n;
		} elsif (! $n->isEmpty) {
			$n->{num}->subA (1);
			return $lambda::undefined if $n->{num}->isZero;
		}
		$atom->newAtomBefore->appendAtoms ("wait", $startTime)->fixAnalyze ("master_wait") if $startTime->{value} > $now;
		$startAtom->setValue (moment_plus ($atom, $startTime, $timespan)) if ! $timespan->isEmpty;
		$atom->repeatBlock ($block);;
		$lambda::pureEmpty;
	}
package lambda::base;
	sub isFhemReading {}
package lambda::clsFhemReading;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
	sub new {lambda::classes::fhemReading->new (@_)}
	sub init {
		my $class = shift;
		$lambda::master->defProperty ($class, "value", lambda::property->new ($lambda::master::string), "r");
		$lambda::master->defProperty ($class, "time", lambda::property->new ($lambda::master::moment), "r");
	}
package lambda::classes::fhemReading;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub new {
		my $self = bless {}, shift;
		($self->{class}, $self->{name}, $self->{device}) = @_;
		$self->{properties}->{value} = lambda::property->new ($lambda::master::string);
		$self->{properties}->{time} = lambda::property->new ($lambda::master::moment);
		$self->{properties}->{value}->{value}->{device} = $self->{properties}->{time}->{value}->{device} = $self->{device};
		$self;
	}
	sub copyTo {
		my ($old, $new) = @_;
		$new->{name} = $old->{name};
		$new->{decive} = $old->{decive};
		$new->{readingID} = $old->{readingID} if defined $old->{readingID};
	}
	sub isFhemReading {1}
	sub string {
		my $self = shift;
		$self->property ("value")->{value}->string . "/" . $self->property ("time")->{value}->string . "/";
	}
package lambda::base;
	sub isDevice {}
package lambda;
	$lambda::error::msgE{"device_01"} = "Klasse 'device' kann nicht instanziiert werden.";
	$lambda::error::msgE{"device_02"} = "Device &&1 kann nicht überschrieben werden.";
	$lambda::error::msgE{"device_03"} = "Readings des Devices &&1 können nicht überschrieben werden.";
package lambda::clsDevice;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
package lambda::classes::device;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub string {"{device " . (shift->{value} || "unknown") . "}"}
	sub isDevice {1}
package lambda::command;
	sub device_overwrite {
		my $device = $_[1];
		$device->isEmpty ? $lambda::empty : lambda::error->new ("device_02", $device);
	}
push (@lambda::master::functions, qw (
	fhemDevice_set . set,fhemDevice,value@symbol,(value@symbol)
	fhemDevice_set1 . set,fhemDevice,string
	fhemDevice_setTime task set,moment,fhemDevice,(value@symbol);set,timespan,fhemDevice,(value@symbol)
	fhemDevice_ReadingVal string [,fhemDevice,word@symbol,]
	fhemDevice_ReadingVal1 string [,fhemDevice,word@symbol,value,]
	fhemDevice_ReadingValHistory string [,fhemDevice,word@symbol,moment,]
	fhemDevice_ReadingTime moment [,fhemDevice,word@symbol,time,]
	fhemDevice_ReadingValState string [,fhemDevice,]
	fhemDevice_Internal string [,fhemDevice,internal,word@symbol,]
	fhemDevice_eq boolean fhemDevice,=,fhemDevice
	fhemDevice_name word fhemDevice,name
	fhemDevice_alias string fhemDevice,alias
	fhemDevice_fhem boolean fhem,string
));
package lambda;
	$lambda::error::msgE{"fhemDevice_01"} = "Keine Datenbank definiert.";
	$lambda::error::msgE{"fhemDevice_02"} = "Fehler bei der Ausführung eines fhem-Kommandos: &&1";
package lambda::base;
	sub isClsFhemDevice {}
	sub isFhemDevice {}
package lambda::clsFhemDevice;
	use vars ('@ISA');
	@ISA = qw (lambda::clsDevice);
	sub new {lambda::classes::fhemDevice->new (@_)}
	sub init {
		my $class = shift;
		my $readingsClass = $lambda::master::collection->copy;
		$readingsClass->{properties}->{of} = lambda::property->new ($lambda::master::class, $lambda::master::fhemReading);
		$readingsClass->{properties}->{default} = lambda::property->new ($lambda::master::fhemReading);
		$lambda::master->defProperty ($class, "readings", lambda::property->new ($readingsClass), "rw");
	}
	sub isClsFhemDevice {1}
package lambda::classes::fhemDevice;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::device);
	sub isFhemDevice {1}
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift;
		my $name = $self->{value} = shift;
		$self->{hash} = $main::defs{$name} if $name;
		my $readingsClass = $self->{class}->{properties}->{readings}->{class};
		$self->{properties}->{readings} = lambda::property->new ($readingsClass, $readingsClass->new);
		Scalar::Util::weaken ($self->{properties}->{readings}->{value}->{device} = $self);
		Scalar::Util::weaken ($self->{device} = $self);
		$self->refresh;
		$self;
	}
	sub refresh {
		my ($device, $atom) = @_;
		$device->saveDB;
		my $hash = $device->{hash};
		my $readingCollectionHash = $device->{properties}->{readings}->{value}->{value};
		my %keys = ();
		$keys{$_} = 1 foreach keys %{$readingCollectionHash};
		foreach (keys %{$hash->{READINGS}}) {
			delete $keys{$_};
			$device->getReadingFromDevice ($_);
		}
		delete $readingCollectionHash->{$_} foreach keys %keys;
		$lambda::undefined;
	}
	sub getReadingFromDevice {
		my ($device, $name) = @_;
		my $collectionHash = $device->{properties}->{readings}->{value}->{value};
		my $readingProperty = $collectionHash->{$name};
		if (! $readingProperty || $readingProperty->{value}->isEmpty) {
			$readingProperty = $collectionHash->{$name} = lambda::property->new ($lambda::master::fhemReading->new ($name, $device));
			$readingProperty->{readOnly} = $readingProperty->{copyProtected} = 1;
			$readingProperty->{value}->{device} = $device;
		}
		my $reading = $readingProperty->{value};
		my $properties = $reading->{properties};
		my $readingValue = $properties->{value};
		my $readingTime = $properties->{time};
		my $VALnew = "";
		my ($TIMEnew, $TIME);
		if (my $readingFhem = $device->{hash}->{READINGS}->{$name}) {
			$VALnew = $readingFhem->{VAL};
			$TIMEnew = $readingFhem->{TIME};
		}
		my $VALold = $readingValue->{value};
		my $TIMEold = $readingTime->{value};
		my $VAL = $lambda::master::string->new ($VALnew);
		if ($TIMEnew) {
			$TIMEnew =~ /(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)/;
			$TIME = $lambda::master::moment->new (Time::Local::timelocal ($6, $5, $4, $3, $2 - 1, $1));
		} else {
			$TIME = $lambda::master::moment->new ();
		}
		$VAL->{device} = $TIME->{device} = $device;
		$readingValue->changeValue ($VAL, $lambda::master);
		$readingTime->changeValue ($TIME, $lambda::master);
		return $lambda::undefined if ! $readingValue->{changed};
		my $dbh = $lambda::master->{hash}->{helper}->{DBHandle};
		return $lambda::undefined if ! $dbh;
		my $readingID = $reading->{readingID};
		if (! $readingID) {
			my $deviceID = $device->{deviceID};
			my $query = $dbh->prepare ("SELECT readingID FROM readings WHERE deviceID=? AND readingName=?");
			$query->execute ($deviceID, $name);
			$readingID = $query->fetchrow_array ();
			if (! $readingID) {
				my $query = $dbh->prepare ("INSERT INTO readings (deviceID,readingName) VALUES (?,?)");
				$query->execute ($deviceID, $name);
				$reading->{readingID} = $readingID = $query->{mysql_insertid};
			}
			$reading->{readingID} = $readingID;
		}
		$lambda::master->{DB}->{saveData}->execute ($readingID, $VALnew, $TIMEnew);
		$lambda::undefined;
	}
	sub compare {
		my ($d1, $d2) = @_;
		$d2->isFhemDevice ? $d1->{value} cmp $d2->{value} : 1;
	}
	sub copyTo {
		my ($from, $to) = @_;
		$to->{value} = $from->{value};
		$to->{hash} = $from->{hash};
	}
	sub string {"{fhemDevice " . (shift->{value} || "unknown") . "}"}
	sub saveDB {
		my $device = shift;
		my $dbh = $lambda::master->{hash}->{helper}->{DBHandle};
		return $lambda::undefined if ! $dbh;
		my $fuuid = $device->{hash}->{FUUID};
		return $lambda::undefined if ! $fuuid;
		my $name = $device->{value};
		my $query = $dbh->prepare ("SELECT deviceID,deviceName FROM devices WHERE FUUID=?");
		$query->execute ($fuuid);
		my ($deviceID, $deviceName) = $query->fetchrow_array;
		if (! $deviceID) {
			$query = $dbh->prepare ("INSERT INTO devices (FUUID,deviceName,TYPE) VALUES (?,?,?)");
			$query->execute ($fuuid, $name, main::InternalVal ($name, "TYPE", undef));
			$deviceID = $query->{mysql_insertid};
		} elsif ($deviceName ne $name) {
			$query = $dbh->prepare ("UPDATE devices SET deviceName=? WHERE deviceID=?");
			$query->execute ($name, $deviceID);
		}
		$device->{deviceID} = $deviceID;
		$lambda::undefined;
	}
package lambda::init;
	sub fhemDevice_set {
		my $atom = shift;
		my ($first, $second, $third, $fourth) = $atom->firsts (4);
		if ($fourth) {
			$atom = $atom->newAtomAfter->appendAtoms ($first, $second, $atom);
			$third = $atom->third;
			my $a = $third->second;
			while ($a) {
				$a->newAtomBefore->setValue ($lambda::master::string->new (" "));
				$a = $a->{next};
			}
			_data_makeString ($third);
			delete $third->{return};
			$third->analyzeCommandList;
		} elsif ((my $symbol = $third->{return})->isSymbol) {
			$third->setValue ($symbol->toWord);
			return $atom->fixAnalyze ("fhemDevice_set1");
		} else {
			$third->newAtomAfter->appendAtoms ($third, lambda::symbol->new ("toString", 1))->analyzeCommandList;
		}
		$lambda::undefined;
	}
	sub fhemDevice_setTime {
		my $atom = shift;
		my ($op, $moment, $device, $string) = $atom->firsts (4);
		if ($moment->{return}->{value}->isA ($lambda::master::timespan)) {
			$moment = $moment->newAtomAfter->appendAtoms("now", $moment);
			delete $moment->first->{return};
			delete $moment->first->{value}->{quote};
			$moment->analyze;
			return if $lambda::error;
		}
		my $thread = $atom->newAtomAfter->appendAtoms ("thread dBlock");
		my $second = $thread->second->appendAtoms ("list list");
		$second->first->appendAtoms ("wait", $moment)->fixAnalyze ("master_wait");
		my $set = $second->second;
		$set->appendAtoms ($op, $device, $string)->analyzeCommandList;
		$atom->erase;
		$thread->fixAnalyze ("master_thread");
		$lambda::undefined;
	}
	sub fhemDevice_ReadingValState {
		my $atom = shift;
		$atom->appendAtoms (lambda::symbol->new ("state", 1), $atom->third);
		fhemDevice_ReadingVal ($atom);
	}
	sub fhemDevice_ReadingVal1 {
		my $atom = shift;
		my ($op1, $dev, $sym, $val, $op2) = $atom->firsts (5);
		$atom->microScript ("'#1 := [&1 " . $sym->{value}->{value} . "]; if (#1 isEmpty) (&2 toString) #1;", $dev, $val);
		$lambda::undefined;
	}
	sub fhemDevice_ReadingVal {
		_fhemDevice_Reading (shift, "value");
	}
	sub fhemDevice_ReadingTime {
		_fhemDevice_Reading (shift, "time");
	}
	sub _fhemDevice_Reading {
		my ($atom, $type) = @_;
		my ($op, $dev, $symbol) = $atom->firsts (3);
		my $new = $atom->newAtomAfter;
		$new->appendAtoms ("list", $type);
		my $new1 = $new->first;
		$new1->appendAtoms ("[ list", $symbol, "]");
		$new1->second->appendAtoms ($dev, "readings");
		$atom->erase;
		$lambda::undefined;
	}
package lambda::command;
	sub fhemDevice_set1 {
		my ($atom, $op, $device, $string) = @_;
		my $cmd = $string->{value};
		return lambda::error->new (0, "leeres Kommando") if $cmd =~ /^\s*$/;
		my $error = main::AnalyzeCommand ($device->{hash}, "set " . $device->{value} . " $cmd");
		$error ? lambda::error->new ("fhemDevice_03", $error) : $lambda::undefined;
	}
	sub fhemDevice_eq {
		$_[1]->compare ($_[3]);
	}
	sub fhemDevice_Internal {
		my ($atom, $op1, $dev, $internal, $symbol) = @_;
		$lambda::master::string->new (main::InternalVal ($dev->{value}, $symbol->{value}, ""));
	}
	sub fhemDevice_name {
		shift;
		$lambda::master::word->new (shift->{value});
	}
	sub fhemDevice_alias {
		shift;
		my $name = shift->{value};
		$lambda::master::string->new (main::AttrVal ($name, "alias", $name));
	}
	sub fhemDevice_fhem {
		my ($atom, $op, $command) = @_;
		my $error = main::AnalyzeCommand (undef, $command->string);
		$error ? lambda::error->new ("fhemDevice_02", $error) : $lambda::undefined;
	}
	sub fhemDevice_ReadingValHistory {
		my ($atom, $op1, $device, $reading, $time) = @_;
		my $dbh = $lambda::master->{helper}->{DBHandle};
		return error->new ("fhemDevice_01") if ! $dbh;
		$lambda::master->{DB}->{readData}->execute ($reading->{value}, $device->{value}, $reading->{value});
	}
package lambda;
	push (@lambda::master::functions, qw (
		fhemLambdaDevice_setReading . initReading,word@symbol,value,(word@symbol,value);setReading,word@symbol,value,(word@symbol,value)
		fhemLambdaDevice_userReading . userReading,word@symbol;userReading,word@symbol,string@symbol
	));
	$lambda::error::msgE{"fhemLambdaDevice_01"} = "userReading für &&1 mit dem widgetOverride '&&2' bereits definiert.";
package lambda::base;
	sub isClsFhemLambdaDevice {}
	sub isFhemLambdaDevice {}
package lambda::clsFhemLambdaDevice;
	use vars ('@ISA');
	@ISA = qw (lambda::clsFhemDevice);
	sub new {lambda::classes::fhemLambdaDevice->new (@_)}
	sub isClsFhemLambdaDevice {1}
package lambda::classes::fhemLambdaDevice;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::fhemDevice);
	sub new {
		my $name = shift;
		bless lambda::classes::fhemDevice->new (@_), $name;
	}
	sub isFhemDeviceDevice {1}
	sub string {"{fhemLambdaDevice " . (shift->{value} || "unknown") . "}"}
package lambda::init;
	sub fhemLambdaDevice_setReading {
		my $second = shift->second;
		while ($second) {
			my $third = $second->{next};
			my $property = $third->{return};
			if ($property->isSymbol) {
				$third->{return} = lambda::property->new ($third->{value} = $property->toWord);
			} elsif (! $property->{class}->isASubclass ($lambda::master::string)) {
				$third = $third->newAtomAfter->appendAtoms ($third, "toString");
				$third->analyzeCommandList;
				return if $lambda::error;
			}
			$second = $third->{next};
		}
		$lambda::undefined;
	}
	sub fhemLambdaDevice_userReading {
		my $atom = shift;
		my ($op, $first, $second) = $atom->firsts (3);
		my $helper = $atom->lambda->{hash}->{helper};
		my $readings = $helper->{readings};
		my $symbol = $first->{value}->{value};
		my $format = $second ? $second->{value}->{value} : "textField";
		return lambda::error->new ("fhemLambdaDevice_01", $symbol, $format) if $readings && $readings->{$symbol} && ($readings->{$symbol} ne $format);
		$helper->{readings}->{$symbol} = $format;
		$atom->erase;
		$lambda::undefined;
	}
package lambda::command;
	sub fhemLambdaDevice_setReading {
		my ($atom, $op, @p) = @_;
		my $set = $op->{value} eq "setReading";
		my $hash = $atom->lambda->{hash};
		my $name = $hash->{NAME};
		main::readingsBeginUpdate ($hash);
		while (@p) {
			my $readingName = shift (@p)->{value};
			my $string = shift (@p);
			my $value = $string->{value};
			if ($set) {
				main::readingsBulkUpdate ($hash, $readingName, $value);
			} elsif ("???" eq main::ReadingsVal ($name, $readingName, "???")) {
				main::readingsBulkUpdate ($hash, $readingName, $value);
			}
		}
		main::readingsEndUpdate ($hash, $set);
		$lambda::undefined;
	}
push (@lambda::master::functions, qw (
	fhemHomematicDevice_Channel fhemHomematicDevice fhemHomematicDevice,channel_01;
	fhemHomematicDevice_Channel fhemHomematicDevice fhemHomematicDevice,channel_02;
	fhemHomematicDevice_Channel fhemHomematicDevice fhemHomematicDevice,channel_03;
	fhemHomematicDevice_Channel fhemHomematicDevice fhemHomematicDevice,channel_04;
	fhemHomematicDevice_Channel fhemHomematicDevice fhemHomematicDevice,channel_05;
	fhemHomematicDevice_Channel fhemHomematicDevice fhemHomematicDevice,channel_06;
	fhemHomematicDevice_Channel fhemHomematicDevice fhemHomematicDevice,channel_07;
	fhemHomematicDevice_Channel fhemHomematicDevice fhemHomematicDevice,channel_08;
	fhemHomematicDevice_Channel fhemHomematicDevice fhemHomematicDevice,channel_09;
));
package lambda::clsFhemHomematicDevice;
	use vars ('@ISA');
	@ISA = qw (lambda::clsFhemDevice);
	sub new {lambda::classes::fhemHomematicDevice->new (@_)}
package lambda::classes::fhemHomematicDevice;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::fhemDevice);
	sub new {
		my $className = shift;
		bless lambda::classes::fhemDevice->new (@_), $className;
	}
	sub string {"{fhemHomematicDevice " . (shift->{value} || "unknown") . "}"}
package lambda::command;
	sub fhemHomematicDevice_Channel {
		my ($atom, $device, $channel) = @_;
		return $device if $device->isEmpty;
		my $devName = $device->{value};
		my $chaName = $channel->{value};
		my $name = main::InternalVal ($devName, $chaName, "");
		return lambda::error->new (16, "$devName.$chaName") if ! $name;
		$lambda::master->getDevice ($name)->{value};
	}
package lambda;
	push (@lambda::master::functions, qw (
		astronomy_sunrise moment astronomy,sunrise
		astronomy_sunset moment astronomy,sunset
	));
package lambda::clsAstronomy;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
	use constant cpi12 => lambda::pi / 12;
	use constant c180pi => 180 / lambda::pi;
	use constant cpi180 => lambda::pi / 180;
	use constant ct => 1 / lambda::daySeconds;
	use constant r => 1;
	sub new {lambda::classes::astronomy->new (@_)}
	sub init {
		my ($sun, $lo, $la) = @_;
		$lambda::master->defProperty ($sun, "longitude", lambda::property->new ($lambda::master::number->newFromString ($lo)), "rw");
		$lambda::master->defProperty ($sun, "latitude", lambda::property->new ($lambda::master::number->newFromString ($la)), "rw");
		$lambda::master->defProperty ($sun, "elevation", lambda::property->new ($lambda::master::number->new), "r");
		$lambda::master->defProperty ($sun, "azimut", lambda::property->new ($lambda::master::number->new), "r");
	}
	sub refresh {
		my ($class, $sun, $atom) = @_;
		my $sunTime = time;
		return if $sunTime == $sun->{moment};
		$sun->{moment} = $sunTime;
		my $longitude = $sun->property ("longitude")->{value}->value * cpi180;
		my $phi = $sun->property ("latitude")->{value}->value * cpi180;
		my $n = ($sunTime - 946728000) * ct;
		my $l = 4.89495042 + 0.0172027924 * $n;
		my $g = 6.240040768 + 0.01720197 * $n;
		my $L = $l + 0.033423055 * sin ($g) + 0.000349066 * sin ($g + $g);
		my $eps = 0.409087723 - 0.000000006981317 * $n;
		my $sL = sin ($L);
		my $alpha = atan2 (cos ($eps) * $sL, cos ($L));
		my $delta = asin (sin ($eps) * $sL);
		my $n0 = int ($n + 0.5) - 0.5;
		my $thetaG = 6.697376 + 0.0657098 * $n0 + 24.065712 * ($n - $n0);
		my $theta = cpi12 * $thetaG + $longitude;
		my $tau = $theta - $alpha;
		my $ctau = cos ($tau);
		my $sphi = sin ($phi);
		my $cphi = cos ($phi);
		my $azimut = atan2 (sin ($tau), $ctau * $sphi - tan ($delta) * $cphi) * c180pi;
		my $h = asin (cos ($delta) * $ctau * $cphi + sin ($delta) * $sphi);
		my $elevation = c180pi * $h + 0.017 / tan ($h + 0.00313756004 / ($h + 0.089185));
		$sun->{properties}->{azimut}->changeValue ($lambda::master::number->newFromString (int (0.5 + $azimut * r), r), $atom);
		$sun->{properties}->{elevation}->changeValue ($lambda::master::number->newFromString (int (0.5 + $elevation * r), r), $atom);
	}
	sub asin {
		my $x = shift;
		2 * atan2 ($x, 1 + sqrt ((1 - $x) * (1 + $x)));
	}
	sub tan {
		my $x = shift;
		my $c = cos ($x);
		$c ? sin ($x) / $c : 1E10;
	}
package lambda::classes::astronomy;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift;
		$self->{moment} = -1;
		$self->{properties}->{azimut} = $self->property ("azimut")->copy;
		$self->{properties}->{elevation} = $self->property ("elevation")->copy;
		$self;
	}
	sub string {
		my $self = shift;
		my $lo = $self->property ("longitude")->{value}->string;
		my $la = $self->property ("latitude")->{value}->string;
		"longitude:$lo°,latitude:$la°";
	}
package lambda::command;
	sub _convertDate {
		my $t = moment_today ();
		shift =~ m/(\d+):(\d+):(\d+)/;
		$t->{value} += 60 * (60 * $1 + $2) + $3;
		$t;
	}
	sub astronomy_sunrise {_convertDate (main::sunrise ())}
	sub astronomy_sunset {_convertDate (main::sunset ())}
package lambda;
	push (@lambda::master::functions1, qw (
		xmlTag_new xmlTag new,xmlTag
		xmlTag_new1 xmlTag new,xmlTag,word
	));
	$lambda::error::msgE{"xmlTag_01"} = "new xmlTag; - nicht zulässig! Inhalt kann keine leere Zeichenkette sein.";
package lambda::base;
	sub isXmlTag {}
package lambda::clsXmlTag;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
	sub new {lambda::classes::xmlTag->new (@_)}
package lambda::classes::xmlTag;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub isXmlTag {1}
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift;
		$self->{value} = shift || "";
		$self;
	}
 	sub string {"<" . shift->{value} . ">"}
package lambda::init;
	sub xmlTag_new {lambda::error->new ("xmlTag_01")}
package lambda::command;
	sub xmlTag_new1 {
		my ($atom, $op, $class, $word) = @_;
		$class->new ($word->{value});
	}
package lambda;
	push (@lambda::master::functions, qw (
		xmlElement_addAttribute . xmlElement,attribute,@symbol,value,(@symbol,value)
		xmlElement_delAttribute . delete,xmlElement,attribute,@symbol,(@symbol)
	));
	push (@lambda::master::functions1, qw (
		xmlElement_new xmlElement new,#xmlElement;new,#xmlElement,@*
	));
	$lambda::error::msgE{"xmlElement_01"} = "new 'xmlElement'; - nicht zulässig! <tag> fehlt.";
package lambda::base;
	sub isClsXmlElement {}
	sub isXmlElement {}
package lambda::clsValue;
	sub isClsXmlElement {shift->isASubclass ($lambda::master::xmlElement)}
package lambda::value;
	sub isXmlElement {shift->{class}->isClsXmlElement}
package lambda::clsXmlElement;
	use vars ('@ISA');
	@ISA = qw (lambda::clsStack);
	sub new {lambda::classes::xmlElement->new (@_)}
	sub init {
		my $xmlElement = shift;
		$lambda::master->defProperty ($xmlElement, "of", lambda::property->new ($lambda::master::class, $lambda::master::value), "rW");
		$lambda::master->defProperty ($xmlElement, "tag", lambda::property->new ($lambda::master::xmlTag), "rw");
		$lambda::master->defProperty ($xmlElement, "id", lambda::property->new ($lambda::master::word->new ("0")), "r");
		$lambda::master->defProperty ($xmlElement, "attributes", lambda::property->new ($lambda::master::collection, $lambda::master::collection->new), "rw");
	}
package lambda::classes::xmlElement;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::stack);
	my $xmlId = 0;
	sub new {
		my $self = bless {},shift;
		$self->{class} = shift;
		$self->{properties}->{id} = lambda::property->new ($lambda::master::word->new (++$xmlId));
		my @content = ();
		$self->{value} = \@content;
		$self;
	}
	sub string {
		my $self = shift;
		my $tag = $self->{properties}->{tag}->{value}->{value};
		my $id = $self->{properties}->{id}->{value}->{value};
		my $s = "<$tag id=\"$id\"";
		my $attr = $self->property ("attributes")->{value}->{value};
		$s .= " $_=\"" . $attr->{$_}->{value}->string . "\"" foreach keys %{$attr};
		my $c = "";
		$c .= $_->{value}->string foreach @{$self->{value}};
		$c ? "$s>$c</$tag>" : "$s />";
	}
package lambda::init;
	sub xmlElement_new {
		my ($first, $second, $third, $fourth) = shift->firsts (4);
		$third && $fourth && $third->{return}->isSymbol ("tag") && $fourth->{return}->{value}->isXmlTag ? lambda::property->new ($lambda::master::xmlElement) : lambda::error->new ("xmlElement_01");
	}
package lambda::command;
	sub xmlElement_addAttribute {
		my ($atom, $xml, $op, @par) = @_;
		$xml->property ("attributes")->{value}->putElement ((shift @par)->{value}, shift @par, $atom) while @par;
		$lambda::undefined;
	}
	sub xmlElement_delAttribute {
		my ($atom, $op1, $xml, $op2, @par) = @_;
		$xml->property ("attributes")->{value}->delElement ((shift @par)->{value}, $atom) while @par;
		$lambda::undefined;
	}
	sub xmlElement_new {
		my $self = $_[2]->new;
		$self->{properties}->{tag} = lambda::property->new ($_[4]);
		$self;
	}
package lambda;
	no warnings 'qw';
	push (@lambda::master::functions, qw (
		html5_new . html,string
	));
package lambda::base;
	sub isHtml5 {}
package lambda::clsHtml5;
	use vars ('@ISA');
	@ISA = qw (lambda::clsValue);
	sub new {lambda::html5->new (@_)}
package lambda::html5;
	use vars ('@ISA');
	@ISA = qw (lambda::classes::value);
	sub new {
		my $self = bless {}, shift;
		$self->{class} = shift;
		$self;
	}
	sub isHtml5 {1}
	sub string {"<!doctype html>" . shift->{html}->string}
package lambda::command;
	sub html5_new {
		my ($atom, $op, $titel) = @_;
		my $self = lambda::data::new ("html5", $atom);
		$self->{html} = $lambda::master::xmlElement->new ("html");
		$self->{titel} = $lambda::master::xmlElement->new ("titel", $titel->string);
		$self->{head} = $lambda::master::xmlElement->new ("head", $self->{titel}->string);
		$self->{body} = $lambda::master::xmlElement->new ("body");
	}
package lambda;
	use vars ('@ISA');
	@ISA = qw (lambda::thread);
	our %atoms;
	our $my = lambda::symbol->new ("my");
	our $undefined = lambda::undefined->new;
	$undefined->{id} = $undefined->id;
	our $terminate = lambda::terminate->new;
	our $wait = lambda::wait->new;
	our $pureEmpty = lambda::empty->new;
	our $error;
	our $emptyString;
	our $blank;
	our $true;
	our $false;
	our $one;
	our $ten;
	our $script;
	our @script;
	our $debug = "";
	our $microSript;
	sub new {
		my ($className, $hash, $root) = @_;
		my $lambda = bless lambda::thread->new ($root), $className;
		$lambda::script .= "}";
		$lambda->{hash} = $hash;
		$lambda->{totalTerm} = lambda::term->new;
		$hash->{helper}->{lambda} = $lambda;
		my $property = $lambda::master->getDevice ($hash->{NAME});
		$lambda->defSymbol (lambda::symbol->new ("myDevice"), $property);
		undef $error;
		$lambda->blockFromScript;
		$error ? $error : $lambda;
	}
	sub isLambda {1}
	sub scriptXml {
		my $lambda = shift;
		my $reading = $lambda::master->{hash}->{READINGS}->{"debug.path"};
		my $path = $reading->{VAL} if $reading;
		$path =~ s/\/$//;
		my $file = $path ."/" . $lambda->{value} . "html";
		open (DATEI, ">$file") or return lambda::error->new (70, $file, $!);
		print DATEI "<!DOCTYPE html>\n";
		print DATEI "<html lang=\"de\">\n";
		print DATEI "<head>\n";
		print DATEI "<meta charset=\"utf-8\" />\n";
		print DATEI "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n";
		print DATEI "<title>lambda-script</title>\n";
		print DATEI "<script src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.js\"></script>\n";
		print DATEI "<script> \$(function(){\$.get(\"hallo.html\",function(data){\$(\"p\").html(data);});})</script>\n";
		print DATEI "<style type=\"text/css\">\n";
		print DATEI "body {font-family:monospace;}\n";
		print DATEI "span.popup span {display:none;position:relative}\n";
		print DATEI "span.popup:hover span {display:block;position:absolute;left:60px;top:40px;z-index:10;background:#eee;border:solid ccc;padding:10px;color:#333;font-size:small}\n";
		print DATEI "div {margin-left:10px;}\n";
		print DATEI ".device {color:red;}\n";
		print DATEI ".value {color:blue;}\n";
		print DATEI ".class {font-style:bold; color:blue;}\n";
		print DATEI "</style>\n";
		print DATEI "</head>\n";
		print DATEI "<body>\n";
		my $t = $lambda->toScriptXml;
		$t =~ s/^(.*?)\{(.*)/$1$2/m;
		$t =~ s/(.*)}(.*)/$1$2/m;
		print DATEI "$t\n";
		print DATEI "<p></p>";
		print DATEI "</body>\n";
		print DATEI "</html>\n";
		close (DATEI);
		$lambda::undefined;
	}
	sub addInFunktionalProperties {
		my ($properties, $sublist, $devicesOnly) = @_;
		my $next = $sublist->{first};
		while ($next) {
			my $list = $next->{value};
			if ($list->isList) {
				addInFunktionalProperties ($properties, $list, $devicesOnly);
			} else {
				my $property = $next->{return};
				if ($property->isProperty) {
					my $value = $property->{value};
					if ($value->isDevice) {
						$properties->{$property} = $property;
					} elsif ($devicesOnly) {
					} elsif ($value->isList) {
						$properties->{$property} = $property;
					} elsif ($next->{value}->{constant}) {
					} else {
						$properties->{$property} = $property;
					}
				}
			}
			$next = $next->{next};
		}
		my $function = $sublist->{function};
		if ($function) {
			my $devices = $function->{devices};
			$properties->{$_} = $devices->{$_} foreach keys %{$devices};
		}
	}
	sub prepare {
		my $script = "";
		my $commentBlock;
		foreach (@_) {
			chomp ($_);
			$commentBlock = 1 if $_ =~ /^\s*\/#/;
			if (! ($commentBlock || $_ =~ /^\s*$|^\s*#/)) {
				$_ =~ s/^\s+|\s+$//g;
				$script .= $script ? " $_" : $_;
			}
			undef $commentBlock if $_ =~ /^\s*#+\//;
		}
		$script;
	}
	sub erase {
		my $lambda = $_[0];
		return 1 if ! defined $lambda->{id}; #?
		delete $lambda->{totalTerm};
		delete $lambda->{hash};
		delete $lambda->{script};
		delete $lambda->{interuptTime};
		lambda::thread::erase ($lambda);
	}
package main;
	use constant lambda_Master => "lambda_Master";
	our $readingFnAttributes;
	our $lambda_interruptTime = 0.5;
	our $lambda_isNotMasterInitialize = 1;
	our $lambda_lastTime;
	sub lambda_Initialize {
		my $hash = shift;
		$hash->{DefFn}    = "lambda_Define";
		$hash->{NotifyFn} = "lambda_Notify";
		$hash->{AttrFn}   = "lambda_Attr";
		$hash->{SetFn}    = "lambda_Set";
		$hash->{AttrList} = "mode:autostart,disabled root configFile " . $readingFnAttributes;
		undef;
	}
	sub lambda_Define {
		my $hash = shift;
		return lambda_MasterDefine ($hash) if $hash->{NAME} eq lambda_Master;
		setNotifyDev ($hash, "global");
		$hash->{DEF} = "log \"Hallo FHEM!\";" if !$hash->{DEF};
		lambda_State ($hash, "initialized");
	}
	sub lambda_MasterDefine {
		my $hash = shift;
		$hash->{DEF} = "# " . $hash->{NAME};
		AnalyzeCommand (undef, "deletereading " . lambda_Master . " .*");
		lambda::master->new ($hash);
		readingsSingleUpdate ($hash, "state", "active", 0);
		readingsSingleUpdate ($hash, "readingDB", "inactive", 0);
		readingsSingleUpdate ($hash, "global.interruptTime", $lambda_interruptTime, 0);
		undef;
	}
	sub lambda_Notify {
		my ($hash, $devHash) = @_;
		my $name = $hash->{NAME};
		return lambda_MasterNotify (@_) if $name eq lambda_Master;
		my $devName = $devHash->{NAME};
		my @events = @{deviceEvents ($devHash, 1)};
		return undef if !(grep (m/^INITIALIZED$|^REREADCFG$/, @events));
		my $masterHash = $main::defs {lambda_Master};
		if (!$masterHash) {
			my $error = AnalyzeCommand (undef, "define " . lambda_Master . " lambda");
			return $error if $error;
			$masterHash = $main::defs {lambda_Master};
		} elsif ($masterHash->{TYPE} ne "lambda") {
			return "Device '" . lambda_Master . "' ist nicht vom Typ 'lambda'.";
		}
		lambda_Attr ("set", $name, "root", AttrVal ($name, "root", lambda_Master));
	}
	sub lambda_MasterNotify {
		my ($hash, $devHash) = @_;
		my $devName = $devHash->{NAME};
		if ($devName eq "global" || $lambda_isNotMasterInitialize) {
			my @events = @{deviceEvents ($devHash, 1)};
			foreach (@events) {
				if ($_ =~ m/^INITIALIZED$|^REREADCFG$/) {
					lambda_ReadConfigFile ($hash);
					undef $lambda_isNotMasterInitialize;
					lambda_Set ($hash, $hash->{NAME}, "start");
					$lambda::master->getDevice ($_) foreach keys %main::defs;
				} elsif ($_ =~ m/^DEFINED\s+(.*)\s*$/) {
					$lambda::master->getDevice ($1);
				} elsif ($_ =~ m/^DELETED\s+(.*)\s*$/) {
					$lambda::master->delDevice ($1);
				} elsif ($_ eq "SHUTDOWN") {
					my $dbh = $hash->{helper}->{DBHandle};
					$dbh->disconnect if $dbh;
				}
			}
			return undef;
		}
		return undef if ReadingsVal (lambda_Master, "state", "?") ne "active";
		lambda_CheckDB ($hash);
		my $devProperty = $lambda::master->{value}->{properties}->{$devName};
		$devProperty ? $devProperty->{value}->refresh : $lambda::master->getDevice ($devName);
		$lambda::master->{go} ? undef : lambda_Go ();
	}
	sub lambda_Attr {
		my ($cmd, $name, $attrName, $attrValue) = @_;
		return lambda_MasterAttr (@_) if $name eq lambda_Master;
		my $hash = $main::defs {$name};
		if (!$attrName) {
		} elsif ($attrName eq "root") {
			if ($cmd eq "del") {
				return undef if !$main::init_done;
				my $rootHash = $main::defs {AttrVal ($name, "root", lambda_Master)};
				lambda_Stop ($hash, "canceled", undef) if lambda_isRunning ($hash);
				$rootHash->{ROOT} =~ s/\b$name\b|^,+|,+$//g;
				$rootHash->{ROOT} =~ s/,,/,/;
				delete $rootHash->{ROOT} if !$rootHash->{ROOT};
			} elsif ($cmd eq "set") {
				return undef if !$main::init_done;
				lambda_Attr ("del", $name, $attrName) if AttrVal ($name, $attrName, "?") ne "?";
				my $rootHash = $main::defs {$attrValue};
				return "$attrValue ist kein lambda-Device! " if !$rootHash || $rootHash->{TYPE} ne "lambda";
				my $root = $attrValue;
				while ($root ne "?") {
					return "$name darf nicht rekursiv von sich selbst abhängen!" if $name eq $attrValue;
					$root = AttrVal ($root, $attrName, "?");
				}
				lambda_Stop ($hash, "canceled", undef) if lambda_isRunning ($hash);
				if ($rootHash->{ROOT}) {
					$rootHash->{ROOT} = join (",", sort (split (",", $rootHash->{ROOT}), $name)) if $rootHash->{ROOT} !~ /\b$name\b/;
				} else {
					 $rootHash->{ROOT} = $name;
				}
			} else {
				return "\"$cmd $name $attrName $attrValue\" nicht zulässig.";
			}
		} elsif ($attrName eq "configFile") {
			return "Attribut \"$attrName\" ist nur in " . lambda_Master . " erlaubt.";
		}
		undef;
	}
	sub lambda_MasterAttr {
		my ($cmd, $name, $attrName, $attrValue) = @_;
		if (!$attrName) {
		} elsif ($attrName eq "configFile") {
			if ($cmd eq "set") {
				lambda_ReadConfigFile ($main::defs {$name}, $attrValue);
			} elsif ($cmd eq "del") {
				lambda_MasterDefine ($main::defs {$name});
			}
		} elsif ($attrName eq "root" || $attrName eq "mode")  {
			return "Attribut $attrName in $name unzulässig!";
		}
		undef;
	}
	sub lambda_Set {
		my ($hash, $name, $cmd, @parameter) = @_;
		return "\"set $name\" needs at least one argument" unless (defined ($cmd));
		return lambda_MasterSet (@_) if $name eq lambda_Master;
		my $helper = $hash->{helper};
		my $userReadings = $helper->{readings};
		if ($cmd eq "start" || ($helper->{debug} = $cmd eq "debug")) {
			return undef if lambda_isRunning ($hash);
			my $rootName = AttrVal ($name, "root", lambda_Master);
			my $rootHash = $main::defs {$rootName};
			my $root = $rootName;
			while ($root ne "?") {
				$root = AttrVal ($root, "root", "?");
				return "$rootName darf nicht rekursiv von sich selbst abhängen!" if $root eq $rootName;
			}
			if ($rootName ne lambda_Master && (! lambda_isRunning ($rootHash))) {
				my $error = lambda_Set ($rootHash, $rootName, "start");
				return "root-Device $rootName lässt sich nicht starten.\n$error" if $error;
			}
			Log3 ($hash, 3, "lambda $name wird compiliert.");
			my $error = lambda_Compile ($hash, $rootHash);
			return $error if $error;
			Log3 ($hash, 2, "lambda $name wird gestartet.");
			$hash->{TIME_START} = lambda_Time ();
			lambda_Go ();
		} elsif ($cmd eq "stop") {
			return undef if !lambda_isRunning ($hash);
			my @root = lambda_RootScripts ($hash);
			$hash->{helper}->{root} = \@root;
			return lambda_Stop ($hash, "canceled", undef);
		} elsif ($cmd eq "restart") {
			lambda_Set ($hash, $name, "stop") if lambda_isRunning ($hash);
			my $result = lambda_Set ($hash, $name, "start");
			return $result if $result;
			foreach (@{$hash->{helper}->{root}}) {
				my $result = lambda_Set ($main::defs {$_}, $_, "start");
				$result = $result ? "$result\n" . $result : $result if $result;
			}
			return $result;
		} elsif ($cmd =~ /^reading_(.*)/) {
			my $readingName = $1 ? $1 : shift @parameter;
			$readingName =~ s/\s//;
			return "Readingname $readingName nicht zulässig!" if !$userReadings->{$readingName};
			readingsSingleUpdate ($hash, $readingName, join (" ", @parameter), 1);
			return undef;
		} else {
			my $return = "unknown argument $cmd, choose one of ";
			$return .= " reading_$_:" . $userReadings->{$_} foreach sort keys %{$userReadings};
			$return .= " stop:noArg restart:noArg";
			return $return;
		}
	}
	sub lambda_RootScripts {
		my $hash = shift;
		my $roots = $hash->{ROOT};
		my @root = $roots ? grep (lambda_isRunning ($main::defs {$_}), split (/,/, $roots)) : ();
		foreach (@root) {
			@root = (@root, lambda_RootScripts ($main::defs {$_}));
		}
		@root;
	}
	sub lambda_MasterSet {
		my ($hash, $name, $cmd, @parameter) = @_;
		if ($cmd eq "readConfigFile") {
			return lambda_ReadConfigFile ($hash);
		} elsif ($cmd eq "start") {
			foreach (sort keys %main::defs) {
				my $hash = $main::defs {$_};
				lambda_Set ($hash, $_, $cmd) if $hash->{TYPE} eq "lambda" && AttrVal ($_, "mode", "?") eq "autostart";
			}
		} elsif ($cmd eq "stop") {
			lambda_Stop ($main::defs {$_}, "canceled") foreach split (",", $hash->{ROOT})
		} else {
			my $return = "unknown argument $cmd, choose one of start:noArg stop:noArg";
			$return .= " readConfigFile:noArg" if (AttrVal ($name, "configFile", "?") ne "?");
			return $return;
		}
		undef;
	}
	sub lambda_Compile {
		my ($hash, $rootHash) = @_;
		lambda_State ($hash, "compile");
		$lambda::script = lambda::prepare (split (/\n/, $hash->{DEF}));
		my $lambda = lambda->new ($hash, $rootHash->{helper}->{lambda});
		return lambda_Stop ($hash, "syntax error\n", $lambda->string) if $lambda->isError;
		readingsDelete ($hash, "error");
		delete $hash->{TIME_STOP};
		delete $hash->{TIME_START};
		undef;
	}
	sub lambda_Go {
		$lambda::master->{go} = 1;
		my $result = lambda::master::go ();
		delete $lambda::master->{go};
		my $hash = $lambda::master->{hash};
		if (!$result) {
			if ($lambda_lastTime) {
				RemoveInternalTimer ($hash);
				undef $lambda_lastTime;
			}
			return undef;
		} elsif ($lambda_lastTime && $lambda_lastTime != $result) {
			RemoveInternalTimer ($hash);
		}
		$lambda_lastTime = $result;
		InternalTimer ($result, "lambda_Go", $hash);
		undef;
	}
	sub lambda_State {
		my ($hash, $state) = @_;
		readingsSingleUpdate ($hash, "state", $state, 0) if $state ne ReadingsVal ($hash->{NAME}, "state", "?");
		undef;
	}
	sub lambda_Stop {
		my ($hash, $state, $result) = @_;
		Log3 ($hash, 0, "lambda $hash->{NAME} $state" . ($result ? $result : ""));
		$hash->{TIME_STOP} = lambda_Time ();
		lambda_Stop ($main::defs {$_}, $state) foreach split (",", $hash->{ROOT} || "");
		$hash->{helper}->{lambda}->erase;
		lambda_State ($hash, $state) if $state;
		$result;
	}
	sub lambda_Time {
		my ($s, $m, $h, $d, $mo, $y) = localtime (shift || time);
		sprintf "%04d-%02d-%02d %02d:%02d:%02d", $y + 1900, ++$mo, $d, $h, $m, $s;
	}
	sub lambda_ReadConfigFile {
		my ($hash, $fileName) = @_;
		$fileName = AttrVal ($hash->{NAME}, "configFile", "?") if !$fileName;
		open (IN, "<$fileName") or return "$!: $fileName";
		my @lines = <IN>;
		close (IN);
		my $section = "global";
		foreach my $line (@lines) {
			my $line0 = $line;
			$line =~ s/^\s+//;
			if ($line =~ m/^#|^\s*$/) {
			} elsif ($line =~ m/\[\s*([^\s]+)\s*\]\s*$/) {
				$section = $1;
			} elsif ($line =~ m/^\s*([^\s]+)\s*=\s*(.*)/) {
				my $name = $1;
				my $value = $2;
				my $unvisible = $name =~ s/^\.//;
				$hash->{helper}->{configFile}->{$section}->{$name} = $value;
				$value = "*****" if $unvisible;
				readingsSingleUpdate ($hash, "$section.$name", $value, 0);
			} else {
				return "Fehlerhafte Zeile in configFile: $line0";
			}
		}
		lambda_CheckDB ($hash);
	}
	sub lambda_CheckDB {
		my $hash = shift;
		my $helper = $hash->{helper};
		my $dbh = $helper->{DBHandle};
		return undef if $dbh && $dbh->ping;
		my $par = $helper->{configFile}->{DB};
		if ($par) {
			my $dbh = $helper->{DBHandle} = DBI->connect ("DBI:" . $par->{DB}, $par->{user}, $par->{password});
			if ($dbh) {
				$dbh->{mysql_auto_reconnect} = 1;
				$dbh->{RaiseError} = 0;
				$dbh->{PrintError} = 0;
				$lambda::master->{DB}->{saveData} = $dbh->prepare ("INSERT INTO data (readingID, value, time) VALUES (?,?,?)");
				$lambda::master->{DB}->{readData} = $dbh->prepare ("SELECT devices.deviceID AS deviceID,readings.readingID AS readingID,data.dataID AS dataID,devices.deviceName AS deviceName,readings.readingName AS readingName,data.value AS value,max(data.time) AS time from ((data join readings on(readings.readingID=data.readingID)) JOIN devices ON (devices.deviceID=readings.deviceID)) WHERE data.time<=? AND readings.readingName=? AND devices.deviceName=?");
				readingsSingleUpdate ($hash, "readingDB", "active", 1);
			} else {
				readingsSingleUpdate ($hash, "readingDB", "interrupted", 1);
			}
		} else {
			readingsSingleUpdate ($hash, "readingDB", "inactive", 1);
			delete $helper->{DBHandle};
		}
		undef;
	}
	sub lambda_isRunning {
		ReadingsVal (shift->{NAME}, "state", "?") eq "running";
	}
	sub lambda_telegramCallBack {
		my ($param, $err, $data) = @_;
		Log3 (undef, 0, "EMPFANG: " . $data);
	}
=pod
=item helper
=item summary Provision of a scripting language to control a FHEM installation
=item summary_DE Bereitstellung einer Scriptsprache zur Steuerung einer FHEM-Installation
=begin html
<a id="lambda"></a>
<h3>lambda: Provision of a scripting language to control a FHEM installation</h3>
<a href="http://www.lambda-script.org" target="_blank">http://www.lambda-script.org</a><br /><br />
=end html
=begin html_DE
<a id="lambda"></a>
<h3>lambda: Bereitstellung einer Scriptsprache zur Steuerung einer FHEM-Installation</h3>
<a href="http://www.lambda-script.org" target="_blank">http://www.lambda-script.org</a><br /><br />
=end html_DE
=cut
1;
