diff --git a/.gitignore b/.gitignore
index b741535df0..af25077dce 100755
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,25 @@ compiler/nimrod*
build/[0-9]_[0-9]
bin/nimrod
+# iOS specific wildcards.
+*.mode1v3
+*.pbxuser
+*.perspective
+*.perspectivev3
+*.swp
+.DS_Store
+project.xcworkspace/
+xcuserdata/
+
+# iOS specific absolute paths
+examples/cross_calculator/ios/resources/ui/*.m
+examples/cross_calculator/ios/tags
+
+# Android specific absolute paths.
+examples/cross_calculator/android/bin/
+examples/cross_calculator/android/gen/
+examples/cross_calculator/android/jni/backend-jni.h
+examples/cross_calculator/android/libs/
+examples/cross_calculator/android/local.properties
+examples/cross_calculator/android/obj/
+examples/cross_calculator/android/tags
diff --git a/examples/cross_calculator/android/AndroidManifest.xml b/examples/cross_calculator/android/AndroidManifest.xml
new file mode 100644
index 0000000000..05b96fb503
--- /dev/null
+++ b/examples/cross_calculator/android/AndroidManifest.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/cross_calculator/android/build.xml b/examples/cross_calculator/android/build.xml
new file mode 100644
index 0000000000..d7c88432a7
--- /dev/null
+++ b/examples/cross_calculator/android/build.xml
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/cross_calculator/android/custom_rules.xml b/examples/cross_calculator/android/custom_rules.xml
new file mode 100644
index 0000000000..91783a50e4
--- /dev/null
+++ b/examples/cross_calculator/android/custom_rules.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/cross_calculator/android/jni/Android.mk b/examples/cross_calculator/android/jni/Android.mk
new file mode 100644
index 0000000000..c1a0feac3a
--- /dev/null
+++ b/examples/cross_calculator/android/jni/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := nimrod
+LOCAL_SRC_FILES := nimcache/backend.c nimcache/system.c
+LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/nimcache
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := backend-jni
+LOCAL_SRC_FILES := backend-jni.c
+LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
+LOCAL_STATIC_LIBRARIES := nimrod
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/examples/cross_calculator/android/jni/backend-jni.c b/examples/cross_calculator/android/jni/backend-jni.c
new file mode 100644
index 0000000000..3d65458ec8
--- /dev/null
+++ b/examples/cross_calculator/android/jni/backend-jni.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include
+#include
+#include "backend-jni.h"
+#include "backend.h"
+
+#define TAG "backend-jni.c"
+
+jint JNICALL Java_com_github_nimrod_crosscalculator_CrossCalculator_myAdd
+ (JNIEnv *env, jobject thiz, jint a, jint b)
+{
+ char buf[256];
+ const jint ret = myAdd(a, b);
+ // Using logging from inside the native bridge to log-debug.
+ sprintf(buf, "a %d + b %d = ret %d", a, b, ret);
+ __android_log_write(ANDROID_LOG_DEBUG, TAG, buf);
+ return ret;
+}
+
+void JNICALL Java_com_github_nimrod_crosscalculator_CrossCalculator_initNimMain
+ (JNIEnv *env, jclass thiz)
+{
+ NimMain();
+ __android_log_write(ANDROID_LOG_DEBUG, TAG, "Nimrod initialised");
+}
+
+// vim:tabstop=2 shiftwidth=2 syntax=c
diff --git a/examples/cross_calculator/android/project.properties b/examples/cross_calculator/android/project.properties
new file mode 100644
index 0000000000..9fb894d9b4
--- /dev/null
+++ b/examples/cross_calculator/android/project.properties
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-3
diff --git a/examples/cross_calculator/android/readme.txt b/examples/cross_calculator/android/readme.txt
new file mode 100644
index 0000000000..f8b16d4fcf
--- /dev/null
+++ b/examples/cross_calculator/android/readme.txt
@@ -0,0 +1,30 @@
+In this directory you will find the Android platform cross-calculator sample.
+
+Due to the nature of Android being java and nimrod generating C code, the build
+process is slightly more complex because jni code has to be written to bridge
+both languages. In a distant future it may be possible for nimrod to generate
+the whole jni bridge, but for the moment this is manual work.
+
+For the jni bridge to work first the java code is compiled with the nimrod code
+just declared as a native method which will be resolved at runtime. The scripts
+nimbuild.sh and jnibuild.sh are in charge of building the nimrod code and
+generating the jni bridge from the java code respectively. Finally, the
+ndk-build command from the android ndk tools has to be run to build the binary
+libary which will be installed along the final apk.
+
+All these steps are wrapped in the ant build script through the customization
+of the -post-compile rule. If you have the android ndk tools installed and you
+modify scripts/nimbuild.sh to point to the directory where you have nimrod
+installed on your system, you can simply run "ant debug" to build everything.
+
+Once the apk is built you can install it on your device or emulator with the
+command "adb install bin/CrossCalculator-debug.apk".
+
+You can use this example as a starting point for your project or look at the
+history of the github project at https://github.com/gradha/nimrod-on-android.
+That repository documents the individual integration steps you would take for
+any Android project (note it uses Eclipse rather than ant to build and
+therefore the build process requires more manual fiddling).
+
+This example runs against the Android level 3 API, meaning devices from
+Android 1.5 and above should be able to run the generated binary.
diff --git a/examples/cross_calculator/android/res/layout/cross_calculator.xml b/examples/cross_calculator/android/res/layout/cross_calculator.xml
new file mode 100644
index 0000000000..11531334c5
--- /dev/null
+++ b/examples/cross_calculator/android/res/layout/cross_calculator.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/cross_calculator/android/res/values/strings.xml b/examples/cross_calculator/android/res/values/strings.xml
new file mode 100644
index 0000000000..05cd3ac93c
--- /dev/null
+++ b/examples/cross_calculator/android/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ CrossCalculator
+
diff --git a/examples/cross_calculator/android/scripts/jnibuild.sh b/examples/cross_calculator/android/scripts/jnibuild.sh
new file mode 100755
index 0000000000..8b61f20f7c
--- /dev/null
+++ b/examples/cross_calculator/android/scripts/jnibuild.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Force errors to fail script.
+set -e
+
+# If we are running from inside the scripts subdir, get out.
+if [ ! -d src ]
+then
+ cd ..
+fi
+
+# Ok, are we out now?
+if [ -d src ]
+then
+ javah -classpath bin/classes \
+ -o jni/backend-jni.h \
+ com.github.nimrod.crosscalculator.CrossCalculator
+else
+ echo "Uh oh, bin/classes directory not found?"
+ echo "Try compiling your java code, or opening in eclipse."
+ exit 1
+fi
diff --git a/examples/cross_calculator/android/scripts/nimbuild.sh b/examples/cross_calculator/android/scripts/nimbuild.sh
new file mode 100755
index 0000000000..97130b8dd6
--- /dev/null
+++ b/examples/cross_calculator/android/scripts/nimbuild.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# Set this to the local or full path of your nimrod compiler
+PATH_TO_NIMROD=~/project/nimrod/bin/nimrod
+# Set this to the location of the nimbase.h file so
+# the script can update it if it changes.
+PATH_TO_NIMBASE=~/project/nimrod/lib/nimbase.h
+
+# Force errors to fail script.
+set -e
+
+# If we are running from inside the scripts subdir, get out.
+if [ ! -d src ]
+then
+ cd ..
+fi
+
+DEST_NIMBASE=jni/nimcache/nimbase.h
+
+# Ok, are we out now?
+if [ -d src ]
+then
+ $PATH_TO_NIMROD c --noMain --app:lib \
+ --nimcache:jni/nimcache --cpu:arm --os:linux \
+ --compileOnly --header ../nimrod_backend/*.nim
+ if [ "${PATH_TO_NIMBASE}" -nt "${DEST_NIMBASE}" ]
+ then
+ echo "Updating nimbase.h"
+ cp "${PATH_TO_NIMBASE}" "${DEST_NIMBASE}"
+ fi
+else
+ echo "Uh oh, src directory not found?"
+ exit 1
+fi
diff --git a/examples/cross_calculator/android/scripts/tags.sh b/examples/cross_calculator/android/scripts/tags.sh
new file mode 100755
index 0000000000..95507064f4
--- /dev/null
+++ b/examples/cross_calculator/android/scripts/tags.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+if [ ! -d src ]
+then
+ cd ..
+fi
+
+if [ -d src ]
+then
+ ~/bin/objctags -R \
+ jni \
+ src
+fi
diff --git a/examples/cross_calculator/android/src/com/github/nimrod/crosscalculator/CrossCalculator.java b/examples/cross_calculator/android/src/com/github/nimrod/crosscalculator/CrossCalculator.java
new file mode 100644
index 0000000000..df2eed5ea2
--- /dev/null
+++ b/examples/cross_calculator/android/src/com/github/nimrod/crosscalculator/CrossCalculator.java
@@ -0,0 +1,80 @@
+package com.github.nimrod.crosscalculator;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+
+public class CrossCalculator extends Activity
+{
+ private static final String TAG = "CrossCalculator";
+ private TextView result_text;
+ private EditText edit_text_a, edit_text_b;
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.cross_calculator);
+
+ final Button button = (Button)findViewById(R.id.add_button);
+ button.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) { addButtonClicked(); } });
+
+ result_text = (TextView)findViewById(R.id.result_text);
+ edit_text_a = (EditText)findViewById(R.id.edit_text_a);
+ edit_text_b = (EditText)findViewById(R.id.edit_text_b);
+ }
+
+ /** Handles clicks on the addition button.
+ * Reads the values form the input fields and performs the calculation.
+ */
+ private void addButtonClicked()
+ {
+ int a = 0, b = 0;
+ String errors = "";
+ final String a_text = edit_text_a.getText().toString();
+ final String b_text = edit_text_b.getText().toString();
+ try {
+ a = Integer.valueOf(a_text, 10);
+ } catch (NumberFormatException e) {
+ errors += "Can't parse a value '" + a_text + "'. ";
+ }
+ try {
+ b = Integer.valueOf(b_text, 10);
+ } catch (NumberFormatException e) {
+ errors += "Can't parse b value '" + b_text + "'";
+ }
+ final int c = myAdd(a, b);
+ result_text.setText("myAdd(" + a + ", " + b + ") = " + c);
+
+ if (errors.length() > 0) {
+ Log.e(TAG, errors);
+ Toast.makeText(this, errors, Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ /* A native method that is implemented by the
+ * 'backend-jni' native library, which is packaged
+ * with this application. Adds to integers.
+ */
+ public native int myAdd(int a, int b);
+
+ /* A native method used to initialise Nimrod.
+ */
+ static public native void initNimMain();
+
+ /* this is used to load the 'backend-jni' library on application
+ * startup. The library has already been unpacked into
+ * /data/data/com.github.nimrod.backendjni/lib/libbackend-jni.so at
+ * installation time by the package manager.
+ */
+ static {
+ System.loadLibrary("backend-jni");
+ initNimMain();
+ }
+}
diff --git a/examples/cross_calculator/ios/cross-calculator.xcodeproj/project.pbxproj b/examples/cross_calculator/ios/cross-calculator.xcodeproj/project.pbxproj
new file mode 100644
index 0000000000..36b43d31bf
--- /dev/null
+++ b/examples/cross_calculator/ios/cross-calculator.xcodeproj/project.pbxproj
@@ -0,0 +1,345 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ D531422A15BC8611005EFF20 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D531422915BC8611005EFF20 /* UIKit.framework */; };
+ D531422C15BC8611005EFF20 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D531422B15BC8611005EFF20 /* Foundation.framework */; };
+ D531422E15BC8611005EFF20 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D531422D15BC8611005EFF20 /* CoreGraphics.framework */; };
+ D531424D15BC87B6005EFF20 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D531424A15BC87B6005EFF20 /* AppDelegate.m */; };
+ D531424E15BC87B6005EFF20 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D531424B15BC87B6005EFF20 /* main.m */; };
+ D531427215BC94B1005EFF20 /* backend.m in Sources */ = {isa = PBXBuildFile; fileRef = D531426F15BC94B1005EFF20 /* backend.m */; };
+ D531427415BC94B1005EFF20 /* system.m in Sources */ = {isa = PBXBuildFile; fileRef = D531427115BC94B1005EFF20 /* system.m */; };
+ D5B6F94815FA8D4C0084A85B /* NRViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D5B6F94615FA8D4C0084A85B /* NRViewController.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ D531422515BC8611005EFF20 /* cross-calculator.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "cross-calculator.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ D531422915BC8611005EFF20 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ D531422B15BC8611005EFF20 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ D531422D15BC8611005EFF20 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ D531424715BC87A5005EFF20 /* cross-calculator-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "cross-calculator-Info.plist"; path = "resources/plist/cross-calculator-Info.plist"; sourceTree = ""; };
+ D531424915BC87B6005EFF20 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = src/AppDelegate.h; sourceTree = ""; };
+ D531424A15BC87B6005EFF20 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = src/AppDelegate.m; sourceTree = ""; };
+ D531424B15BC87B6005EFF20 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = src/main.m; sourceTree = ""; };
+ D531424C15BC87B6005EFF20 /* cross-calculator-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "cross-calculator-Prefix.pch"; path = "src/cross-calculator-Prefix.pch"; sourceTree = ""; };
+ D531426715BC91EF005EFF20 /* tags.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = tags.sh; path = scripts/tags.sh; sourceTree = ""; };
+ D531426815BC91EF005EFF20 /* xcode_prebuild.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = xcode_prebuild.sh; path = scripts/xcode_prebuild.sh; sourceTree = ""; };
+ D531426F15BC94B1005EFF20 /* backend.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = backend.m; path = build/nimcache/backend.m; sourceTree = ""; };
+ D531427115BC94B1005EFF20 /* system.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = system.m; path = build/nimcache/system.m; sourceTree = ""; };
+ D592E19015C7120F005258EA /* backend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = backend.h; path = build/nimcache/backend.h; sourceTree = ""; };
+ D592E19115C71415005258EA /* nimbase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nimbase.h; path = build/nimcache/nimbase.h; sourceTree = ""; };
+ D5B6F94515FA8D4C0084A85B /* NRViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NRViewController.h; path = src/NRViewController.h; sourceTree = ""; };
+ D5B6F94615FA8D4C0084A85B /* NRViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NRViewController.m; path = src/NRViewController.m; sourceTree = ""; };
+ D5B6F96315FB448D0084A85B /* NRViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = NRViewController.xib; path = resources/ui/NRViewController.xib; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ D531422215BC8610005EFF20 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D531422A15BC8611005EFF20 /* UIKit.framework in Frameworks */,
+ D531422C15BC8611005EFF20 /* Foundation.framework in Frameworks */,
+ D531422E15BC8611005EFF20 /* CoreGraphics.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ D531421A15BC8610005EFF20 = {
+ isa = PBXGroup;
+ children = (
+ D531426A15BC93D5005EFF20 /* build */,
+ D531424515BC874E005EFF20 /* resources */,
+ D531426615BC91E1005EFF20 /* scripts */,
+ D531424815BC87AD005EFF20 /* src */,
+ D531422815BC8611005EFF20 /* Frameworks */,
+ D531422615BC8611005EFF20 /* Products */,
+ );
+ sourceTree = "";
+ };
+ D531422615BC8611005EFF20 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ D531422515BC8611005EFF20 /* cross-calculator.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ D531422815BC8611005EFF20 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ D531422915BC8611005EFF20 /* UIKit.framework */,
+ D531422B15BC8611005EFF20 /* Foundation.framework */,
+ D531422D15BC8611005EFF20 /* CoreGraphics.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ D531424515BC874E005EFF20 /* resources */ = {
+ isa = PBXGroup;
+ children = (
+ D531424615BC8756005EFF20 /* plist */,
+ D5B6F96115FB447C0084A85B /* ui */,
+ );
+ name = resources;
+ sourceTree = "";
+ };
+ D531424615BC8756005EFF20 /* plist */ = {
+ isa = PBXGroup;
+ children = (
+ D531424715BC87A5005EFF20 /* cross-calculator-Info.plist */,
+ );
+ name = plist;
+ sourceTree = "";
+ };
+ D531424815BC87AD005EFF20 /* src */ = {
+ isa = PBXGroup;
+ children = (
+ D531424915BC87B6005EFF20 /* AppDelegate.h */,
+ D531424A15BC87B6005EFF20 /* AppDelegate.m */,
+ D531424C15BC87B6005EFF20 /* cross-calculator-Prefix.pch */,
+ D531424B15BC87B6005EFF20 /* main.m */,
+ D5B6F94515FA8D4C0084A85B /* NRViewController.h */,
+ D5B6F94615FA8D4C0084A85B /* NRViewController.m */,
+ );
+ name = src;
+ sourceTree = "";
+ };
+ D531426615BC91E1005EFF20 /* scripts */ = {
+ isa = PBXGroup;
+ children = (
+ D531426715BC91EF005EFF20 /* tags.sh */,
+ D531426815BC91EF005EFF20 /* xcode_prebuild.sh */,
+ );
+ name = scripts;
+ sourceTree = "";
+ };
+ D531426A15BC93D5005EFF20 /* build */ = {
+ isa = PBXGroup;
+ children = (
+ D531426E15BC94A6005EFF20 /* nimrod */,
+ );
+ name = build;
+ sourceTree = "";
+ };
+ D531426E15BC94A6005EFF20 /* nimrod */ = {
+ isa = PBXGroup;
+ children = (
+ D592E19015C7120F005258EA /* backend.h */,
+ D531426F15BC94B1005EFF20 /* backend.m */,
+ D592E19115C71415005258EA /* nimbase.h */,
+ D531427115BC94B1005EFF20 /* system.m */,
+ );
+ name = nimrod;
+ sourceTree = "";
+ };
+ D5B6F96115FB447C0084A85B /* ui */ = {
+ isa = PBXGroup;
+ children = (
+ D5B6F96315FB448D0084A85B /* NRViewController.xib */,
+ );
+ name = ui;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ D531422415BC8610005EFF20 /* cross-calculator */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = D531423D15BC8611005EFF20 /* Build configuration list for PBXNativeTarget "cross-calculator" */;
+ buildPhases = (
+ D531426915BC926C005EFF20 /* ShellScript */,
+ D531422115BC8610005EFF20 /* Sources */,
+ D531422215BC8610005EFF20 /* Frameworks */,
+ D531422315BC8610005EFF20 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "cross-calculator";
+ productName = "cross-calculator";
+ productReference = D531422515BC8611005EFF20 /* cross-calculator.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ D531421C15BC8610005EFF20 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0420;
+ ORGANIZATIONNAME = "Electric Hands Software";
+ };
+ buildConfigurationList = D531421F15BC8610005EFF20 /* Build configuration list for PBXProject "cross-calculator" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ );
+ mainGroup = D531421A15BC8610005EFF20;
+ productRefGroup = D531422615BC8611005EFF20 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ D531422415BC8610005EFF20 /* cross-calculator */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ D531422315BC8610005EFF20 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ D531426915BC926C005EFF20 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = scripts/xcode_prebuild.sh;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ D531422115BC8610005EFF20 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ D531424D15BC87B6005EFF20 /* AppDelegate.m in Sources */,
+ D531424E15BC87B6005EFF20 /* main.m in Sources */,
+ D531427215BC94B1005EFF20 /* backend.m in Sources */,
+ D531427415BC94B1005EFF20 /* system.m in Sources */,
+ D5B6F94815FA8D4C0084A85B /* NRViewController.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ D531423B15BC8611005EFF20 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = (
+ armv7,
+ armv6,
+ );
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_VERSION = "";
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 3.0;
+ OTHER_LDFLAGS = (
+ "-weak_library",
+ /usr/lib/libSystem.B.dylib,
+ );
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ D531423C15BC8611005EFF20 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ARCHS = (
+ armv7,
+ armv6,
+ );
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_VERSION = "";
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 3.0;
+ OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
+ OTHER_LDFLAGS = (
+ "-weak_library",
+ /usr/lib/libSystem.B.dylib,
+ );
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ D531423E15BC8611005EFF20 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "src/cross-calculator-Prefix.pch";
+ INFOPLIST_FILE = "resources/plist/cross-calculator-Info.plist";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Debug;
+ };
+ D531423F15BC8611005EFF20 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "src/cross-calculator-Prefix.pch";
+ INFOPLIST_FILE = "resources/plist/cross-calculator-Info.plist";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ D531421F15BC8610005EFF20 /* Build configuration list for PBXProject "cross-calculator" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ D531423B15BC8611005EFF20 /* Debug */,
+ D531423C15BC8611005EFF20 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ D531423D15BC8611005EFF20 /* Build configuration list for PBXNativeTarget "cross-calculator" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ D531423E15BC8611005EFF20 /* Debug */,
+ D531423F15BC8611005EFF20 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = D531421C15BC8610005EFF20 /* Project object */;
+}
diff --git a/examples/cross_calculator/ios/readme.txt b/examples/cross_calculator/ios/readme.txt
new file mode 100644
index 0000000000..e75db72bf2
--- /dev/null
+++ b/examples/cross_calculator/ios/readme.txt
@@ -0,0 +1,17 @@
+In this directory you will find the iOS platform cross-calculator sample.
+
+The iOS version of the code builds a view controller in charge of displaying
+the interface to the user. The nimrod backend code is compiled into C code and
+put into build/nimrod as a pre-build phase of the project.
+
+When the calculate button is used the view controller calls the nimrod code to
+delegate the logic of the operation and puts the result in a label for display.
+All interface error checks are implemented in the view controller.
+
+You can use this as a starting point for your project or look at the history of
+the github project at https://github.com/gradha/nimrod-on-ios. That repository
+documents the individual integration steps you would take for any iOS project.
+
+This version of the iOS project is known to work with Xcode 4.2 and Xcode
+4.4.1. The final binary can be deployed on iOS 3.x to 5.x supporting all iOS
+platforms and versions available at the moment.
diff --git a/examples/cross_calculator/ios/resources/plist/cross-calculator-Info.plist b/examples/cross_calculator/ios/resources/plist/cross-calculator-Info.plist
new file mode 100644
index 0000000000..758f20e387
--- /dev/null
+++ b/examples/cross_calculator/ios/resources/plist/cross-calculator-Info.plist
@@ -0,0 +1,30 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleDisplayName
+ ${PRODUCT_NAME}
+ CFBundleExecutable
+ ${EXECUTABLE_NAME}
+ CFBundleIconFiles
+
+ CFBundleIdentifier
+ com.github.nimrod.${PRODUCT_NAME:rfc1034identifier}
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ ${PRODUCT_NAME}
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1.0
+ UIApplicationExitsOnSuspend
+
+
+
diff --git a/examples/cross_calculator/ios/resources/ui/NRViewController.xib b/examples/cross_calculator/ios/resources/ui/NRViewController.xib
new file mode 100644
index 0000000000..b260db2afc
--- /dev/null
+++ b/examples/cross_calculator/ios/resources/ui/NRViewController.xib
@@ -0,0 +1,479 @@
+
+
+
+ 0
+ 11E53
+ 2549
+ 1138.47
+ 569.00
+
+
+ IBProxyObject
+ IBUIButton
+ IBUILabel
+ IBUITextField
+ IBUIView
+
+
+ com.apple.InterfaceBuilder.IBCocoaTouchPlugin
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -1
+
+
+ File's Owner
+
+
+ -2
+
+
+
+
+ 14
+
+
+
+
+ 13
+
+
+
+
+ 12
+
+
+
+
+ 11
+
+
+
+
+ 10
+
+
+
+
+ 8
+
+
+
+
+ 7
+
+
+
+
+ 4
+
+
+
+
+ 22
+
+
+
+
+
+
+ NRViewController
+ com.apple.InterfaceBuilder.IBCocoaTouchPlugin
+ UIResponder
+ com.apple.InterfaceBuilder.IBCocoaTouchPlugin
+ com.apple.InterfaceBuilder.IBCocoaTouchPlugin
+ com.apple.InterfaceBuilder.IBCocoaTouchPlugin
+ com.apple.InterfaceBuilder.IBCocoaTouchPlugin
+ com.apple.InterfaceBuilder.IBCocoaTouchPlugin
+ com.apple.InterfaceBuilder.IBCocoaTouchPlugin
+ com.apple.InterfaceBuilder.IBCocoaTouchPlugin
+ com.apple.InterfaceBuilder.IBCocoaTouchPlugin
+ com.apple.InterfaceBuilder.IBCocoaTouchPlugin
+ com.apple.InterfaceBuilder.IBCocoaTouchPlugin
+ com.apple.InterfaceBuilder.IBCocoaTouchPlugin
+
+
+
+
+
+ 22
+
+
+
+
+ NRViewController
+ UIViewController
+
+ id
+ id
+
+
+
+ backgroundTouched
+ id
+
+
+ calculateButtonTouched
+ id
+
+
+
+ UITextField
+ UITextField
+ UIButton
+ UILabel
+
+
+
+ aText
+ UITextField
+
+
+ bText
+ UITextField
+
+
+ calculateButton
+ UIButton
+
+
+ resultLabel
+ UILabel
+
+
+
+ IBProjectSource
+ ./Classes/NRViewController.h
+
+
+
+
+ 0
+ IBCocoaTouchFramework
+
+ com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS
+
+
+ YES
+ 3
+ 1498
+
+
diff --git a/examples/cross_calculator/ios/scripts/tags.sh b/examples/cross_calculator/ios/scripts/tags.sh
new file mode 100755
index 0000000000..111e7a1c0a
--- /dev/null
+++ b/examples/cross_calculator/ios/scripts/tags.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+if [ ! -d src ]
+then
+ cd ..
+fi
+
+if [ -d src ]
+then
+ ~/bin/objctags -R \
+ build/nimcache \
+ src
+fi
diff --git a/examples/cross_calculator/ios/scripts/xcode_prebuild.sh b/examples/cross_calculator/ios/scripts/xcode_prebuild.sh
new file mode 100755
index 0000000000..7626ba0b97
--- /dev/null
+++ b/examples/cross_calculator/ios/scripts/xcode_prebuild.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+# Set this to the full path of your nimrod compiler
+# since Xcode doesn't inherit your user environment.
+PATH_TO_NIMROD=~/project/nimrod/bin/nimrod
+# Set this to the location of the nimbase.h file so
+# the script can update it if it changes.
+PATH_TO_NIMBASE=~/project/nimrod/lib/nimbase.h
+
+# Force errors to fail script.
+set -e
+
+# If we are running from inside the scripts subdir, get out.
+if [ ! -d src ]
+then
+ cd ..
+fi
+
+DEST_NIMBASE=build/nimcache/nimbase.h
+
+# Ok, are we out now?
+if [ -d src ]
+then
+ # You may want to use a wildcard here to compile all nimrod files.
+ $PATH_TO_NIMROD objc --noMain --app:lib \
+ --nimcache:build/nimcache --compileOnly \
+ --header --cpu:i386 ../nimrod_backend/backend.nim
+ if [ "${PATH_TO_NIMBASE}" -nt "${DEST_NIMBASE}" ]
+ then
+ echo "Updating nimbase.h"
+ cp "${PATH_TO_NIMBASE}" "${DEST_NIMBASE}"
+ fi
+else
+ echo "Uh oh, src directory not found?"
+ exit 1
+fi
diff --git a/examples/cross_calculator/ios/src/AppDelegate.h b/examples/cross_calculator/ios/src/AppDelegate.h
new file mode 100644
index 0000000000..a5a8b38522
--- /dev/null
+++ b/examples/cross_calculator/ios/src/AppDelegate.h
@@ -0,0 +1,7 @@
+#import
+
+@interface AppDelegate : UIResponder
+
+@property (strong, nonatomic) UIWindow *window;
+
+@end
diff --git a/examples/cross_calculator/ios/src/AppDelegate.m b/examples/cross_calculator/ios/src/AppDelegate.m
new file mode 100644
index 0000000000..53e7f6188b
--- /dev/null
+++ b/examples/cross_calculator/ios/src/AppDelegate.m
@@ -0,0 +1,39 @@
+#import "AppDelegate.h"
+
+#import "NRViewController.h"
+
+
+@interface AppDelegate ()
+@property (nonatomic, retain) NRViewController *viewController;
+@end
+
+
+@implementation AppDelegate
+
+@synthesize viewController = _viewController;
+@synthesize window = _window;
+
+- (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+ self.window = [[[UIWindow alloc]
+ initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
+
+ self.viewController = [[NRViewController new] autorelease];
+ if ([self.window respondsToSelector:@selector(setRootViewController:)])
+ self.window.rootViewController = self.viewController;
+ else
+ [self.window addSubview:self.viewController.view];
+ [self.window makeKeyAndVisible];
+
+ return YES;
+}
+
+- (void)dealloc
+{
+ [_window release];
+ [_viewController release];
+ [super dealloc];
+}
+
+@end
diff --git a/examples/cross_calculator/ios/src/NRViewController.h b/examples/cross_calculator/ios/src/NRViewController.h
new file mode 100644
index 0000000000..36ba37758c
--- /dev/null
+++ b/examples/cross_calculator/ios/src/NRViewController.h
@@ -0,0 +1,11 @@
+@interface NRViewController : UIViewController
+
+@property (nonatomic, retain) IBOutlet UIButton *calculateButton;
+@property (nonatomic, retain) IBOutlet UITextField *aText;
+@property (nonatomic, retain) IBOutlet UITextField *bText;
+@property (nonatomic, retain) IBOutlet UILabel *resultLabel;
+
+- (IBAction)calculateButtonTouched;
+- (IBAction)backgroundTouched;
+
+@end
\ No newline at end of file
diff --git a/examples/cross_calculator/ios/src/NRViewController.m b/examples/cross_calculator/ios/src/NRViewController.m
new file mode 100644
index 0000000000..bd0df7d6bd
--- /dev/null
+++ b/examples/cross_calculator/ios/src/NRViewController.m
@@ -0,0 +1,210 @@
+#import "NRViewController.h"
+
+#import "backend.h"
+
+
+@implementation NRViewController
+
+@synthesize aText = _aText;
+@synthesize bText = _bText;
+@synthesize calculateButton = _calculateButton;
+@synthesize resultLabel = _resultLabel;
+
+- (void)dealloc
+{
+ [_aText release];
+ [_bText release];
+ [_calculateButton release];
+ [_resultLabel release];
+ [super dealloc];
+}
+
+- (void)viewDidUnload
+{
+ self.calculateButton = nil;
+ self.aText = nil;
+ self.bText = nil;
+ self.resultLabel = nil;
+ [super viewDidUnload];
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:
+ (UIInterfaceOrientation)interfaceOrientation
+{
+ return YES;
+}
+
+/// User wants to calculate the inputs. Well, do it!
+- (IBAction)calculateButtonTouched
+{
+ // Dismiss all keyboards.
+ [self backgroundTouched];
+
+ // Call nimrod code, store the result and display it.
+ const int a = [self.aText.text intValue];
+ const int b = [self.bText.text intValue];
+ const int c = myAdd(a, b);
+ self.resultLabel.text = [NSString stringWithFormat:@"%d + %d = %d",
+ a, b, c];
+}
+
+/// If the user touches the background, dismiss any visible keyboard.
+- (IBAction)backgroundTouched
+{
+ [self.aText resignFirstResponder];
+ [self.bText resignFirstResponder];
+}
+
+/** Custom loadView method for backwards compatiblity.
+ * Unfortunately I've been unable to coerce Xcode 4.4 to generate nib files
+ * which are compatible with my trusty iOS 3.0 ipod touch so in order to be
+ * fully compatible for all devices we have to build the interface manually in
+ * code rather than through the keyed archivers provided by the interface
+ * builder.
+ *
+ * Rather than recreating the user interface manually in code the tool nib2obj
+ * was used on the xib file and slightly modified to fit the original property
+ * names. Which means here is a lot of garbage you would never write in real
+ * life. Please ignore the following "wall of code" for the purposes of
+ * learning Nimrod, this is all just because Apple can't be bothered to
+ * maintain backwards compatibility properly.
+ */
+- (void)loadView
+{
+ [super loadView];
+
+ self.calculateButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
+ self.calculateButton.autoresizesSubviews = YES;
+ self.calculateButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
+ self.calculateButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
+ self.calculateButton.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
+ self.calculateButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
+ self.calculateButton.frame = CGRectMake(193.0, 124.0, 107.0, 37.0);
+ self.calculateButton.tag = 5;
+ [self.calculateButton setTitle:@"Add!" forState:UIControlStateNormal];
+ [self.calculateButton addTarget:self
+ action:@selector(calculateButtonTouched)
+ forControlEvents:UIControlEventTouchUpInside];
+
+ UILabel *label11 = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 124.0, 60.0, 37.0)];
+ label11.adjustsFontSizeToFitWidth = YES;
+ label11.autoresizesSubviews = YES;
+ label11.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
+ label11.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
+ label11.frame = CGRectMake(20.0, 124.0, 60.0, 37.0);
+ label11.tag = 6;
+ label11.text = @"Result:";
+
+ UILabel *label4 = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 34.0)];
+ label4.adjustsFontSizeToFitWidth = YES;
+ label4.autoresizesSubviews = YES;
+ label4.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
+ label4.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
+ label4.frame = CGRectMake(0.0, 0.0, 320.0, 34.0);
+ label4.tag = 2;
+ label4.text = @"Nimrod Crossplatform Calculator";
+ label4.textAlignment = UITextAlignmentCenter;
+
+ UIButton *background_button = [UIButton buttonWithType:UIButtonTypeCustom];
+ background_button.autoresizesSubviews = YES;
+ background_button.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
+ background_button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
+ background_button.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
+ background_button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
+ background_button.frame = CGRectMake(0.0, -10.0, 320.0, 480.0);
+ background_button.tag = 1;
+ [background_button addTarget:self action:@selector(backgroundTouched)
+ forControlEvents:UIControlEventTouchDown];
+
+ self.resultLabel = [[[UILabel alloc] initWithFrame:CGRectMake(88.0, 124.0, 97.0, 37.0)] autorelease];
+ self.resultLabel.adjustsFontSizeToFitWidth = YES;
+ self.resultLabel.autoresizesSubviews = YES;
+ self.resultLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
+ self.resultLabel.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
+ self.resultLabel.frame = CGRectMake(88.0, 124.0, 97.0, 37.0);
+ self.resultLabel.tag = 7;
+ self.resultLabel.text = @"";
+
+ self.aText = [[[UITextField alloc] initWithFrame:CGRectMake(193.0, 42.0, 107.0, 31.0)] autorelease];
+ self.aText.adjustsFontSizeToFitWidth = YES;
+ self.aText.autocapitalizationType = UITextAutocapitalizationTypeNone;
+ self.aText.autocorrectionType = UITextAutocorrectionTypeDefault;
+ self.aText.autoresizesSubviews = YES;
+ self.aText.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
+ self.aText.borderStyle = UITextBorderStyleRoundedRect;
+ self.aText.clearButtonMode = UITextFieldViewModeWhileEditing;
+ self.aText.clearsOnBeginEditing = NO;
+ self.aText.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
+ self.aText.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
+ self.aText.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
+ self.aText.enablesReturnKeyAutomatically = NO;
+ self.aText.frame = CGRectMake(193.0, 42.0, 107.0, 31.0);
+ self.aText.keyboardAppearance = UIKeyboardAppearanceDefault;
+ self.aText.keyboardType = UIKeyboardTypeNumberPad;
+ self.aText.placeholder = @"Integer";
+ self.aText.returnKeyType = UIReturnKeyDefault;
+ self.aText.tag = 8;
+ self.aText.text = @"";
+ self.aText.textAlignment = UITextAlignmentCenter;
+
+ UILabel *label7 = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 42.0, 165.0, 31.0)];
+ label7.adjustsFontSizeToFitWidth = YES;
+ label7.autoresizesSubviews = YES;
+ label7.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
+ label7.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
+ label7.frame = CGRectMake(20.0, 42.0, 165.0, 31.0);
+ label7.tag = 3;
+ label7.text = @"Value A:";
+
+ UILabel *label8 = [[UILabel alloc] initWithFrame:CGRectMake(20.0, 81.0, 165.0, 31.0)];
+ label8.adjustsFontSizeToFitWidth = YES;
+ label8.autoresizesSubviews = YES;
+ label8.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
+ label8.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
+ label8.frame = CGRectMake(20.0, 81.0, 165.0, 31.0);
+ label8.tag = 4;
+ label8.text = @"Value B:";
+
+ self.bText = [[[UITextField alloc]
+ initWithFrame:CGRectMake(193.0, 81.0, 107.0, 31.0)] autorelease];
+ self.bText.adjustsFontSizeToFitWidth = YES;
+ self.bText.autocapitalizationType = UITextAutocapitalizationTypeNone;
+ self.bText.autocorrectionType = UITextAutocorrectionTypeDefault;
+ self.bText.autoresizesSubviews = YES;
+ self.bText.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
+ self.bText.borderStyle = UITextBorderStyleRoundedRect;
+ self.bText.clearButtonMode = UITextFieldViewModeWhileEditing;
+ self.bText.clearsOnBeginEditing = NO;
+ self.bText.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
+ self.bText.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
+ self.bText.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
+ self.bText.enablesReturnKeyAutomatically = NO;
+ self.bText.frame = CGRectMake(193.0, 81.0, 107.0, 31.0);
+ self.bText.keyboardAppearance = UIKeyboardAppearanceDefault;
+ self.bText.keyboardType = UIKeyboardTypeNumberPad;
+ self.bText.placeholder = @"Integer";
+ self.bText.returnKeyType = UIReturnKeyDefault;
+ self.bText.tag = 9;
+ self.bText.text = @"";
+ self.bText.textAlignment = UITextAlignmentCenter;
+
+ self.view.frame = CGRectMake(0.0, 20.0, 320.0, 460.0);
+ self.view.autoresizesSubviews = YES;
+ self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ self.view.backgroundColor = [UIColor colorWithWhite:1.000 alpha:1.000];
+ self.view.contentStretch = CGRectFromString(@"{{0, 0}, {1, 1}}");
+ self.view.frame = CGRectMake(0.0, 20.0, 320.0, 460.0);
+ self.view.tag = 0;
+
+ [self.view addSubview:background_button];
+ [self.view addSubview:label4];
+ [self.view addSubview:label7];
+ [self.view addSubview:label8];
+ [self.view addSubview:self.calculateButton];
+ [self.view addSubview:label11];
+ [self.view addSubview:self.resultLabel];
+ [self.view addSubview:self.aText];
+ [self.view addSubview:self.bText];
+}
+
+@end
diff --git a/examples/cross_calculator/ios/src/cross-calculator-Prefix.pch b/examples/cross_calculator/ios/src/cross-calculator-Prefix.pch
new file mode 100644
index 0000000000..2f331ed435
--- /dev/null
+++ b/examples/cross_calculator/ios/src/cross-calculator-Prefix.pch
@@ -0,0 +1,10 @@
+#import
+
+#ifndef __IPHONE_3_0
+#warning "This project uses features only available in iOS SDK 3.0 and later."
+#endif
+
+#ifdef __OBJC__
+ #import
+ #import
+#endif
diff --git a/examples/cross_calculator/ios/src/main.m b/examples/cross_calculator/ios/src/main.m
new file mode 100644
index 0000000000..7866684fe5
--- /dev/null
+++ b/examples/cross_calculator/ios/src/main.m
@@ -0,0 +1,13 @@
+#import
+
+#import "AppDelegate.h"
+#import "backend.h"
+
+int main(int argc, char *argv[])
+{
+ @autoreleasepool {
+ NimMain();
+ return UIApplicationMain(argc, argv, nil,
+ NSStringFromClass([AppDelegate class]));
+ }
+}
diff --git a/examples/lazarus/nimlaz.lpi b/examples/cross_calculator/lazarus/nimlaz.lpi
similarity index 100%
rename from examples/lazarus/nimlaz.lpi
rename to examples/cross_calculator/lazarus/nimlaz.lpi
diff --git a/examples/lazarus/nimlaz.lpr b/examples/cross_calculator/lazarus/nimlaz.lpr
similarity index 100%
rename from examples/lazarus/nimlaz.lpr
rename to examples/cross_calculator/lazarus/nimlaz.lpr
diff --git a/examples/lazarus/nimlaz.lrs b/examples/cross_calculator/lazarus/nimlaz.lrs
similarity index 100%
rename from examples/lazarus/nimlaz.lrs
rename to examples/cross_calculator/lazarus/nimlaz.lrs
diff --git a/examples/lazarus/nimlaz.rc b/examples/cross_calculator/lazarus/nimlaz.rc
similarity index 100%
rename from examples/lazarus/nimlaz.rc
rename to examples/cross_calculator/lazarus/nimlaz.rc
diff --git a/examples/lazarus/readme.txt b/examples/cross_calculator/lazarus/readme.txt
similarity index 100%
rename from examples/lazarus/readme.txt
rename to examples/cross_calculator/lazarus/readme.txt
diff --git a/examples/lazarus/unit1.lfm b/examples/cross_calculator/lazarus/unit1.lfm
similarity index 100%
rename from examples/lazarus/unit1.lfm
rename to examples/cross_calculator/lazarus/unit1.lfm
diff --git a/examples/lazarus/unit1.pas b/examples/cross_calculator/lazarus/unit1.pas
similarity index 100%
rename from examples/lazarus/unit1.pas
rename to examples/cross_calculator/lazarus/unit1.pas
diff --git a/examples/lazarus/backend.nim b/examples/cross_calculator/nimrod_backend/backend.nim
similarity index 57%
rename from examples/lazarus/backend.nim
rename to examples/cross_calculator/nimrod_backend/backend.nim
index 64f0c5bf71..ffa4311f9d 100755
--- a/examples/lazarus/backend.nim
+++ b/examples/cross_calculator/nimrod_backend/backend.nim
@@ -1,4 +1,4 @@
-# Backend for the Lazarus GUI
+# Backend for the different user interfaces.
proc myAdd*(x, y: int): int {.cdecl, exportc.} =
result = x + y
diff --git a/examples/cross_calculator/readme.txt b/examples/cross_calculator/readme.txt
new file mode 100644
index 0000000000..e59cb7e54d
--- /dev/null
+++ b/examples/cross_calculator/readme.txt
@@ -0,0 +1,11 @@
+The cross platform calculator illustrates how to use Nimrod to create a backend
+called by different native user interfaces.
+
+Since the purpose of the example is to show how the cross platform code
+interacts with Nimrod the actual backend code is just a simple addition proc.
+By keeping your program logic in Nimrod you can easily reuse it in different
+platforms.
+
+To avoid duplication of code, the backend code lies in a separate directory and
+each platform compiles it with a different custom build process, usually
+generating C code in a temporary build directory.
diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim
index 9c086c6757..ac6d3c3ced 100755
--- a/lib/pure/hashes.nim
+++ b/lib/pure/hashes.nim
@@ -122,3 +122,7 @@ proc hash*[T: tuple](x: T): THash =
result = result !& hash(f)
result = !$result
+proc hash*(x: float): THash {.inline.} =
+ var y = x + 1.0
+ result = cast[ptr THash](addr(y))[]
+
diff --git a/tests/run/thashes.nim b/tests/run/thashes.nim
new file mode 100644
index 0000000000..c442b43fba
--- /dev/null
+++ b/tests/run/thashes.nim
@@ -0,0 +1,8 @@
+import unittest
+import hashes
+
+suite "hashes":
+ suite "hashing":
+ test "0.0 and -0.0 should have the same hash value":
+ var dummy = 0.0
+ check hash(dummy) == hash(-dummy)
diff --git a/tests/run/tmath.nim b/tests/run/tmath.nim
index 65124306eb..a86a3b84ce 100644
--- a/tests/run/tmath.nim
+++ b/tests/run/tmath.nim
@@ -25,14 +25,12 @@ suite "random int":
check rand >= 100
suite "random float":
- # Enable this once #197 has been resolved
- # test "there might be some randomness":
- # var set = initSet[float](128)
- # for i in 1..10:
- # for j in 1..10:
- # randomize()
- # incl(set, random(1.0))
- # check len(set) == 100
+ test "there might be some randomness":
+ var set = initSet[float](128)
+ randomize()
+ for i in 1..100:
+ incl(set, random(1.0))
+ check len(set) == 100
test "single number bounds work":
randomize()
var rand: float