#!/bin/bash # If this file has already been sourced, just return test $(EVALUATOR__FUNCTIONS_BUILTIN_SH+true) && return declare -g EVALUATOR__FUNCTIONS_BUILTIN_SH=true source ${BASH_SOURCE%/*}/common.sh source ${BASH_SOURCE%/*}/variables.sh source ${BASH_SOURCE%/*}/environment.sh proc evaluator::functions::builtin::add { if [[ ${EVALUATOR_DEBUG} == 1 ]] { stderr "evaluator::functions::builtin::add $(@)" ; } declare env="$(1)" declare functionName="$(2)" declare argsToken="$(3)" variable::LinkedList::length $(argsToken) if [[ $RESULT < 2 ]] { stderr "add not valid with less than 2 arguments" exit 1 } variable::LinkedList::first $(argsToken) ; declare headToken="$(RESULT)" evaluator::eval $(env) $(RESULT) variable::value $(RESULT) ; declare result="$(RESULT)" variable::LinkedList::rest $(argsToken) ; declare rest="$(RESULT)" declare currentToken declare currentValue while ! variable::LinkedList::isEmpty_c $(rest) { variable::LinkedList::first $(rest) evaluator::eval $(env) $(RESULT) setglobal currentToken = $(RESULT) if ! variable::type::instanceOf $(currentToken) Integer { variable::type $(currentToken) stderr "Cannot add type [$(RESULT)]" exit 1 } variable::value $(currentToken) ; setglobal currentValue = $(RESULT) sh-expr ' result += ${currentValue} ' variable::LinkedList::rest $(rest); setglobal rest = $(RESULT) } variable::new Integer $(result) setglobal RESULT = $(RESULT) } proc evaluator::functions::builtin::subtract { if [[ ${EVALUATOR_DEBUG} == 1 ]] { stderr "evaluator::functions::builtin::subtract $(@)" ; } declare env="$(1)" declare functionName="$(2)" declare argsToken="$(3)" variable::LinkedList::length $(argsToken) if [[ $RESULT < 2 ]] { stderr "add not valid with less than 2 arguments" exit 1 } variable::LinkedList::first $(argsToken) ; declare headToken="$(RESULT)" evaluator::eval $(env) $(RESULT) variable::value $(RESULT) ; declare result="$(RESULT)" variable::LinkedList::rest $(argsToken) ; declare rest="$(RESULT)" declare currentToken declare currentValue while ! variable::LinkedList::isEmpty_c $(rest) { variable::LinkedList::first $(rest) evaluator::eval $(envToken) $(RESULT) setglobal currentToken = $(RESULT) if ! variable::type::instanceOf $(currentToken) Integer { variable::type $(currentToken) stderr "Cannot add type [$(RESULT)]" exit 1 } variable::value $(currentToken) ; setglobal currentValue = $(RESULT) sh-expr ' result -= "${currentValue}" ' variable::LinkedList::rest $(rest); setglobal rest = $(RESULT) } variable::new Integer $(result) setglobal RESULT = $(RESULT) } proc evaluator::functions::builtin::multiply { if [[ ${EVALUATOR_DEBUG} == 1 ]] { stderr "evaluator::functions::builtin::multiply $(@)" ; } declare env="$(1)" declare functionName="$(2)" declare argsToken="$(3)" variable::LinkedList::length $(argsToken) if [[ $RESULT < 2 ]] { stderr "add not valid with less than 2 arguments" exit 1 } variable::LinkedList::first $(argsToken) ; declare headToken="$(RESULT)" evaluator::eval $(env) $(RESULT) variable::value $(RESULT) ; declare result="$(RESULT)" variable::LinkedList::rest $(argsToken) ; declare rest="$(RESULT)" declare currentToken declare currentValue while ! variable::LinkedList::isEmpty_c $(rest) { variable::LinkedList::first $(rest) evaluator::eval $(envToken) $(RESULT) setglobal currentToken = $(RESULT) if ! variable::type::instanceOf $(currentToken) Integer { variable::type $(currentToken) stderr "Cannot add type [$(RESULT)]" exit 1 } variable::value $(currentToken) ; setglobal currentValue = $(RESULT) sh-expr ' result *= "${currentValue}" ' variable::LinkedList::rest $(rest); setglobal rest = $(RESULT) } variable::new Integer $(result) setglobal RESULT = $(RESULT) } proc evaluator::functions::builtin::divide { if [[ ${EVALUATOR_DEBUG} == 1 ]] { stderr "evaluator::functions::builtin::divide $(@)" ; } declare env="$(1)" declare functionName="$(2)" declare argsToken="$(3)" variable::LinkedList::length $(argsToken) if [[ $RESULT < 2 ]] { stderr "add not valid with less than 2 arguments" exit 1 } variable::LinkedList::first $(argsToken) ; declare headToken="$(RESULT)" evaluator::eval $(env) $(RESULT) variable::value $(RESULT) ; declare result="$(RESULT)" variable::LinkedList::rest $(argsToken) ; declare rest="$(RESULT)" declare currentToken declare currentValue while ! variable::LinkedList::isEmpty_c $(rest) { variable::LinkedList::first $(rest) evaluator::eval $(envToken) $(RESULT) setglobal currentToken = $(RESULT) if ! variable::type::instanceOf $(currentToken) Integer { variable::type $(currentToken) stderr "Cannot add type [$(RESULT)]" exit 1 } variable::value $(currentToken) ; setglobal currentValue = $(RESULT) sh-expr ' result /= "${currentValue}" ' variable::LinkedList::rest $(rest); setglobal rest = $(RESULT) } variable::new Integer $(result) setglobal RESULT = $(RESULT) } proc evaluator::functions::builtin::equals { if [[ ${EVALUATOR_DEBUG} == 1 ]] { stderr "evaluator::functions::builtin::equals $(@)" ; } declare env="$(1)" declare functionName="$(2)" declare argsToken="$(3)" variable::LinkedList::length $(argsToken) if [[ $RESULT < 2 ]] { stderr "add not valid with less than 2 arguments" exit 1 } variable::LinkedList::first $(argsToken) ; declare headToken="$(RESULT)" evaluator::eval $(env) $(RESULT) variable::value $(RESULT) ; declare first="$(RESULT)" variable::LinkedList::rest $(argsToken) ; declare rest="$(RESULT)" declare currentToken declare currentValue while ! variable::LinkedList::isEmpty_c $(rest) { variable::LinkedList::first $(rest) evaluator::eval $(envToken) $(RESULT) setglobal currentToken = $(RESULT) if ! variable::type::instanceOf $(currentToken) Integer { variable::type $(currentToken) stderr "Cannot add type [$(RESULT)]" exit 1 } variable::value $(currentToken) ; setglobal currentValue = $(RESULT) if [[ $first -ne $currentValue ]] { variable::new Boolean false setglobal RESULT = $(RESULT) return } variable::LinkedList::rest $(rest); setglobal rest = $(RESULT) } variable::new Boolean true setglobal RESULT = $(RESULT) return } proc evaluator::functions::builtin::greaterthan { if [[ ${EVALUATOR_DEBUG} == 1 ]] { stderr "evaluator::functions::builtin::equals $(@)" ; } declare env="$(1)" declare functionName="$(2)" declare argsToken="$(3)" variable::LinkedList::length $(argsToken) if [[ $RESULT < 2 ]] { stderr "add not valid with less than 2 arguments" exit 1 } variable::LinkedList::first $(argsToken) ; declare headToken="$(RESULT)" evaluator::eval $(env) $(RESULT) variable::value $(RESULT) ; declare first="$(RESULT)" variable::LinkedList::rest $(argsToken) ; declare rest="$(RESULT)" declare currentToken declare currentValue while ! variable::LinkedList::isEmpty_c $(rest) { variable::LinkedList::first $(rest) evaluator::eval $(envToken) $(RESULT) setglobal currentToken = $(RESULT) if ! variable::type::instanceOf $(currentToken) Integer { variable::type $(currentToken) stderr "Cannot add type [$(RESULT)]" exit 1 } variable::value $(currentToken) ; setglobal currentValue = $(RESULT) if [[ ! $first -gt $currentValue ]] { variable::new Boolean false setglobal RESULT = $(RESULT) return } variable::LinkedList::rest $(rest); setglobal rest = $(RESULT) } variable::new Boolean true setglobal RESULT = $(RESULT) return } proc evaluator::functions::builtin::lessthan { if [[ ${EVALUATOR_DEBUG} == 1 ]] { stderr "evaluator::functions::builtin::equals $(@)" ; } declare env="$(1)" declare functionName="$(2)" declare argsToken="$(3)" variable::LinkedList::length $(argsToken) if [[ $RESULT < 2 ]] { stderr "add not valid with less than 2 arguments" exit 1 } variable::LinkedList::first $(argsToken) ; declare headToken="$(RESULT)" evaluator::eval $(env) $(RESULT) variable::value $(RESULT) ; declare first="$(RESULT)" variable::LinkedList::rest $(argsToken) ; declare rest="$(RESULT)" declare currentToken declare currentValue while ! variable::LinkedList::isEmpty_c $(rest) { variable::LinkedList::first $(rest) evaluator::eval $(envToken) $(RESULT) setglobal currentToken = $(RESULT) if ! variable::type::instanceOf $(currentToken) Integer { variable::type $(currentToken) stderr "Cannot add type [$(RESULT)]" exit 1 } variable::value $(currentToken) ; setglobal currentValue = $(RESULT) if [[ ! $first -lt $currentValue ]] { variable::new Boolean false setglobal RESULT = $(RESULT) return } variable::LinkedList::rest $(rest); setglobal rest = $(RESULT) } variable::new Boolean true setglobal RESULT = $(RESULT) return } proc evaluator::functions::builtin::greaterthanorequal { if [[ ${EVALUATOR_DEBUG} == 1 ]] { stderr "evaluator::functions::builtin::equals $(@)" ; } declare env="$(1)" declare functionName="$(2)" declare argsToken="$(3)" variable::LinkedList::length $(argsToken) if [[ $RESULT < 2 ]] { stderr "add not valid with less than 2 arguments" exit 1 } variable::LinkedList::first $(argsToken) ; declare headToken="$(RESULT)" evaluator::eval $(env) $(RESULT) variable::value $(RESULT) ; declare first="$(RESULT)" variable::LinkedList::rest $(argsToken) ; declare rest="$(RESULT)" declare currentToken declare currentValue while ! variable::LinkedList::isEmpty_c $(rest) { variable::LinkedList::first $(rest) evaluator::eval $(envToken) $(RESULT) setglobal currentToken = $(RESULT) if ! variable::type::instanceOf $(currentToken) Integer { variable::type $(currentToken) stderr "Cannot add type [$(RESULT)]" exit 1 } variable::value $(currentToken) ; setglobal currentValue = $(RESULT) if [[ ! $first -ge $currentValue ]] { variable::new Boolean false setglobal RESULT = $(RESULT) return } variable::LinkedList::rest $(rest); setglobal rest = $(RESULT) } variable::new Boolean true setglobal RESULT = $(RESULT) return } proc evaluator::functions::builtin::lessthanorequal { if [[ ${EVALUATOR_DEBUG} == 1 ]] { stderr "evaluator::functions::builtin::equals $(@)" ; } declare env="$(1)" declare functionName="$(2)" declare argsToken="$(3)" variable::LinkedList::length $(argsToken) if [[ $RESULT < 2 ]] { stderr "add not valid with less than 2 arguments" exit 1 } variable::LinkedList::first $(argsToken) ; declare headToken="$(RESULT)" evaluator::eval $(env) $(RESULT) variable::value $(RESULT) ; declare first="$(RESULT)" variable::LinkedList::rest $(argsToken) ; declare rest="$(RESULT)" declare currentToken declare currentValue while ! variable::LinkedList::isEmpty_c $(rest) { variable::LinkedList::first $(rest) evaluator::eval $(envToken) $(RESULT) setglobal currentToken = $(RESULT) if ! variable::type::instanceOf $(currentToken) Integer { variable::type $(currentToken) stderr "Cannot add type [$(RESULT)]" exit 1 } variable::value $(currentToken) ; setglobal currentValue = $(RESULT) if [[ ! $first -le $currentValue ]] { variable::new Boolean false setglobal RESULT = $(RESULT) return } variable::LinkedList::rest $(rest); setglobal rest = $(RESULT) } variable::new Boolean true setglobal RESULT = $(RESULT) return }