inbetween firing the
+ // hyperlink. Technically that might be correct but complicates
+ // how we manage focus. So if we detect this manually invoke
+ // the click to skip over that behavoir
+ e.target->click
+ e.stop
+ return
+ }
+
cur := sel.indexes
newsel := cur.dup
@@ -1007,17 +1032,20 @@ using graphics
if (cur < 0) cur = cur.not - 1
pre := colx[cur] == scrollx ? cur-1 : cur
scrollTo(0.max(pre), null)
+ return
case Key.right:
cur := colx.binarySearch(scrollx)
if (cur < 0) cur = cur.not - 1
scrollTo((numCols-1).min(cur+1), null)
+ return
case Key.up:
if (sel.indexes.isEmpty)
{
updateSel([selFirstVis])
scrollTo(null, firstVisRow)
+ return
}
else
{
@@ -1025,6 +1053,7 @@ using graphics
prev := pivot - 1
updateSel([view.rowViewToModel(prev)])
scrollTo(null, prev)
+ return
}
case Key.down:
@@ -1032,6 +1061,7 @@ using graphics
{
updateSel([selFirstVis])
scrollTo(null, firstVisRow)
+ return
}
else
{
@@ -1039,6 +1069,7 @@ using graphics
next := pivot + 1
updateSel([view.rowViewToModel(next)])
scrollTo(null, next)
+ return
}
}
@@ -1048,6 +1079,9 @@ using graphics
cbAction?.call(this)
return
}
+
+ // else bubble up to callback
+ if (e.type == "keydown") return cbKeyDown?.call(e)
}
@NoDoc Void updateSel(Int[] newsel)
@@ -1083,6 +1117,8 @@ using graphics
private Func? cbBeforeSelect
private Func? cbSelect
private Func? cbAction
+ private Func? cbSort
+ private Func? cbKeyDown
private Str:Func cbTableEvent := [:]
private Func? cbHeaderPopup
@@ -1315,7 +1351,7 @@ internal const class TablePos
override Void onUpdate(Int[] oldIndexes, Int[] newIndexes)
{
oldIndexes.each |i| { if (i < max) view.table.refreshRow(view.rowModelToView(i)) }
- newIndexes.each |i| { view.table.refreshRow(view.rowModelToView(i)) }
+ newIndexes.each |i| { if (i < max) view.table.refreshRow(view.rowModelToView(i)) }
}
private TableView view
}
diff --git a/com.xored.f4.fantom/fantom/src/email/build.fan b/com.xored.f4.fantom/fantom/src/email/build.fan
index 8fdca6c7..32421143 100755
--- a/com.xored.f4.fantom/fantom/src/email/build.fan
+++ b/com.xored.f4.fantom/fantom/src/email/build.fan
@@ -19,12 +19,12 @@ class Build : BuildPod
podName = "email"
summary = "Email support"
meta = ["org.name": "Fantom",
- "org.uri": "http://fantom.org/",
+ "org.uri": "https://fantom.org/",
"proj.name": "Fantom Core",
- "proj.uri": "http://fantom.org/",
+ "proj.uri": "https://fantom.org/",
"license.name": "Academic Free License 3.0",
- "vcs.name": "Mercurial",
- "vcs.uri": "https://bitbucket.org/fantom/fan-1.0/"]
+ "vcs.name": "Git",
+ "vcs.uri": "https://github.com/fantom-lang/fantom"]
depends = ["sys 1.0", "inet 1.0"]
srcDirs = [`fan/`, `test/`]
docSrc = true
diff --git a/com.xored.f4.fantom/fantom/src/fandoc/build.fan b/com.xored.f4.fantom/fantom/src/fandoc/build.fan
index 9c204d89..95f6fdb5 100755
--- a/com.xored.f4.fantom/fantom/src/fandoc/build.fan
+++ b/com.xored.f4.fantom/fantom/src/fandoc/build.fan
@@ -19,12 +19,12 @@ class Build : BuildPod
podName = "fandoc"
summary = "Fandoc parser and DOM"
meta = ["org.name": "Fantom",
- "org.uri": "http://fantom.org/",
+ "org.uri": "https://fantom.org/",
"proj.name": "Fantom Core",
- "proj.uri": "http://fantom.org/",
+ "proj.uri": "https://fantom.org/",
"license.name": "Academic Free License 3.0",
- "vcs.name": "Mercurial",
- "vcs.uri": "https://bitbucket.org/fantom/fan-1.0/"]
+ "vcs.name": "Git",
+ "vcs.uri": "https://github.com/fantom-lang/fantom"]
depends = ["sys 1.0"]
srcDirs = [`fan/`, `test/`]
docSrc = true
diff --git a/com.xored.f4.fantom/fantom/src/fandoc/fan/DocModel.fan b/com.xored.f4.fantom/fantom/src/fandoc/fan/DocModel.fan
index 1f99eac2..6d3816d9 100755
--- a/com.xored.f4.fantom/fantom/src/fandoc/fan/DocModel.fan
+++ b/com.xored.f4.fantom/fantom/src/fandoc/fan/DocModel.fan
@@ -53,6 +53,16 @@ abstract class DocNode
**
abstract Void write(DocWriter out)
+ **
+ ** Is this an inline versus a block node.
+ **
+ abstract Bool isInline()
+
+ **
+ ** Is this a block element versus an inline element.
+ **
+ Bool isBlock() { return !isInline }
+
**
** Debug dump to output stream.
**
@@ -112,6 +122,11 @@ abstract class DocNode
{
return parent?.children?.last === this
}
+
+ **
+ ** Get all the DocText children as a string
+ **
+ abstract Str toText()
}
**************************************************************************
@@ -135,7 +150,11 @@ class DocText : DocNode
out.text(this)
}
- override Str toStr() { return str }
+ override Bool isInline() { true }
+
+ override Str toText() { str }
+
+ override Str toStr() { str }
Str str
}
@@ -157,16 +176,6 @@ abstract class DocElem : DocNode
**
abstract Str htmlName()
- **
- ** Is this an inline versus a block element.
- **
- abstract Bool isInline()
-
- **
- ** Is this a block element versus an inline element.
- **
- Bool isBlock() { return !isInline }
-
**
** Write this element and its children to the specified DocWriter.
**
@@ -194,6 +203,11 @@ abstract class DocElem : DocNode
**
DocNode[] children() { return kids.ro }
+ **
+ ** Iterate the children nodes
+ **
+ Void eachChild(|DocNode| f) { kids.each(f) }
+
@Deprecated { msg = "Use add()" }
This addChild(DocNode node) { add(node) }
@@ -274,6 +288,16 @@ abstract class DocElem : DocNode
return this
}
+ **
+ ** Get all the DocText children as a string
+ **
+ override Str toText()
+ {
+ s := StrBuf()
+ kids.each |kid| { s.join(kid.toText, " ") }
+ return s.toStr
+ }
+
//////////////////////////////////////////////////////////////////////////
// Path
//////////////////////////////////////////////////////////////////////////
@@ -350,7 +374,7 @@ class Heading : DocElem
override DocNodeId id() { return DocNodeId.heading }
override Str htmlName() { return "h$level" }
override Bool isInline() { return false }
- Str title() { children.first.toStr }
+ Str title() { toText }
const Int level
}
@@ -570,6 +594,7 @@ class Image : DocElem
Str uri
Str alt
Str? size // formatted {w}x{h}
+ Int line
}
**************************************************************************
diff --git a/com.xored.f4.fantom/fantom/src/fandoc/fan/FandocDocWriter.fan b/com.xored.f4.fantom/fantom/src/fandoc/fan/FandocDocWriter.fan
index 84c16e6e..f8287fad 100644
--- a/com.xored.f4.fantom/fantom/src/fandoc/fan/FandocDocWriter.fan
+++ b/com.xored.f4.fantom/fantom/src/fandoc/fan/FandocDocWriter.fan
@@ -265,7 +265,7 @@ internal class ListIndex
private static Int:Str sortr(Int:Str unordered)
{
// no ordered literal map... grr...
- // http://fantom.org/sidewalk/topic/1837#c14431
+ // https://fantom.org/forum/topic/1837#c14431
sorted := [:] { it.ordered = true }
unordered.keys.sortr.each { sorted[it] = unordered[it] }
return sorted
diff --git a/com.xored.f4.fantom/fantom/src/fandoc/fan/InlineParser.fan b/com.xored.f4.fantom/fantom/src/fandoc/fan/InlineParser.fan
index 52ad0d0d..52e84751 100755
--- a/com.xored.f4.fantom/fantom/src/fandoc/fan/InlineParser.fan
+++ b/com.xored.f4.fantom/fantom/src/fandoc/fan/InlineParser.fan
@@ -225,6 +225,7 @@ internal class InlineParser
uri := uri
img := Image(uri, alt)
img.size = size
+ img.line = this.line
return img
}
diff --git a/com.xored.f4.fantom/fantom/src/fandoc/pod.fandoc b/com.xored.f4.fantom/fantom/src/fandoc/pod.fandoc
index 43670488..9a39d70a 100755
--- a/com.xored.f4.fantom/fantom/src/fandoc/pod.fandoc
+++ b/com.xored.f4.fantom/fantom/src/fandoc/pod.fandoc
@@ -43,16 +43,16 @@ pre>
- Strong: **foo bar**
- Emphasis: *foo bar*
- Strong+Emphasis: ** *foo bar* **
- - Hyperlink: `http://fantom.org/`
- - Hyperlink: [Fantom Home Page]`http://fantom.org/`
+ - Hyperlink: `https://fantom.org/`
+ - Hyperlink: [Fantom Home Page]`https://fantom.org/`
- ![fan logo]`http://fantom.org/pod/fantomws/res/img/fantom.png`
+ ![fan logo]`https://fantom.org/pod/fantomws/res/img/fantom.png`
- ![fan logo][80x18]`http://fantom.org/pod/fantomws/res/img/fantom.png`
+ ![fan logo][80x18]`https://fantom.org/pod/fantomws/res/img/fantom.png`
- [![alt]`http://fantom.org/pod/fantomws/res/img/fantom.png`]`http://fantom.org/`
+ [![alt]`https://fantom.org/pod/fantomws/res/img/fantom.png`]`https://fantom.org/`
-#include
-#include
-#include "launcher.h"
-#include "utils.h"
-
-#define KEY_LEN 256
-typedef HRESULT (*_CorBindToRuntimeEx)(LPCWSTR,LPCWSTR,DWORD,REFCLSID,REFIID,LPVOID FAR *);
-ICLRRuntimeHost *pClrHost;
-
-//////////////////////////////////////////////////////////////////////////
-// Init CLR
-//////////////////////////////////////////////////////////////////////////
-
-/**
- * Check for .NET framework version 2.0 using registery.
- */
-int checkDotnetFwVer()
-{
- if (debug) printf("-- findDotnetVer\n");
-
- // query registry to get installed .NET Framework versions
- const char* key= "SOFTWARE\\Microsoft\\.NETFramework\\policy";
- HKEY hKey;
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
- //return err("Cannot read registry: %s", key);
- return err(".NET Framework v2.0 not found");
-
- // list all installed versions of fw
- if (debug) printf("-- registry keys:\n");
-
- DWORD dwIndex = 0;
- DWORD cbName = KEY_LEN;
- char val[KEY_LEN];
- int fwFound = -1;
-
- while ((ERROR_NO_MORE_ITEMS !=
- RegEnumKeyEx(hKey, dwIndex, val, &cbName, NULL, NULL, NULL, NULL)))
- {
- if (debug) printf("-- %s\n", val);
- if (strcmp(val, "v2.0") == 0) fwFound = ERROR_SUCCESS;
- if (strcmp(val, "V2.0") == 0) fwFound = ERROR_SUCCESS;
- dwIndex++;
- cbName = KEY_LEN;
- }
-
- // close
- RegCloseKey(hKey);
-
- // return result
- if (fwFound != ERROR_SUCCESS)
- return err(".NET Framework v2.0 not found");
-
- return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Load the CLR
-//////////////////////////////////////////////////////////////////////////
-
-int loadClr()
-{
- if (debug) printf("-- loadClr\n");
-
- // dynamically load mscoree.dll
- if (debug) printf("-- load mscoree.dll\n");
- HINSTANCE dll = LoadLibrary("mscoree.dll");
- if (dll == NULL)
- return err("Cannot load library: mscoree.dll");
-
- // query for CorBindToRuntimeEx
- _CorBindToRuntimeEx corBindToRuntimeEx =
- (_CorBindToRuntimeEx)GetProcAddress(dll, "CorBindToRuntimeEx");
- if (corBindToRuntimeEx == NULL)
- return err("Cannot find CorBindToRuntimeEx in mscoree.dll");
-
- // load CLR
- HRESULT hr = corBindToRuntimeEx(
- NULL, // desired CLR version (NULL = latest)
- NULL, // desired GC flavor (NULL = workstation)
- 0, // desired startup flags
- CLSID_CLRRuntimeHost, // CLSID of CLR
- IID_ICLRRuntimeHost, // IID of ICLRRuntimeHost
- (PVOID*)&pClrHost); // return COM interface
-
- if (!SUCCEEDED(pClrHost))
- return err("Cannot load CLR Host");
-
- return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Run the main method
-//////////////////////////////////////////////////////////////////////////
-
-int runDotnetMain()
-{
- // initialize and start the CLR
- pClrHost->Start();
-
- // get sys path
- char sysPath[MAX_PATH];
- strcpy(sysPath, fanHome);
- strcat(sysPath, "\\lib\\dotnet\\sys.dll");
- ULONG sz = strlen(sysPath) + 1;
- LPWSTR wSysPath = new WCHAR[sz];
- MultiByteToWideChar(CP_ACP, 0, sysPath, sz, wSysPath, sz);
- if (debug)
- {
- printf("-- sysPath = %s\n", sysPath);
- printf("-- wSysPath = %S\n", wSysPath);
- }
-
- // figure out main
- char mainClassName[256];
- sprintf(mainClassName, "Fanx.Tools.%s", FAN_TOOL);
- sz = strlen(mainClassName) + 1;
- LPWSTR wMainClassName = new WCHAR[sz];
- MultiByteToWideChar(CP_ACP, 0, mainClassName, sz, wMainClassName, sz);
- if (debug)
- {
- printf("-- mainClassName = %s\n", mainClassName);
- printf("-- wMainClassName = %S\n", wMainClassName);
- }
-
- // since we only have a single str to work with
- // stuff everything into our reserved str, delimited
- // with newlines
-
- char reserved[1024];
- reserved[0] = '\0'; // need this or we get garbage at beginning of str
- strcat(reserved, fanHome);
- strcat(reserved, "\n");
- for (int i=0; i 0) strcat(reserved, "\n");
- strcat(reserved, fanArgv[i]);
- }
- sz = strlen(reserved) + 1;
- LPWSTR wReserved = new WCHAR[sz];
- MultiByteToWideChar(CP_ACP, 0, reserved, sz, wReserved, sz);
- if (debug) printf("-- wReserved = %S\n", wReserved);
-
- DWORD retVal = 0;
- HRESULT hr = pClrHost->ExecuteInDefaultAppDomain(
- wSysPath, wMainClassName, L"run", wReserved, &retVal);
-
- if (debug)
- {
- printf("-- Managed code returned %d\n", retVal);
- printf("-- HRESULT = %d\n", hr);
- }
-
- if (!SUCCEEDED(hr))
- return err("Could not run %s\n", mainClassName);
-
- return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// .NET Main
-//////////////////////////////////////////////////////////////////////////
-
-int runDotnet()
-{
- if (checkDotnetFwVer()) return -1;
- if (loadClr()) return -1;
- if (runDotnetMain()) return -1;
- return 0;
-}
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/launcher/dotnet.h b/com.xored.f4.fantom/fantom/src/launcher/dotnet.h
deleted file mode 100755
index e0adf8da..00000000
--- a/com.xored.f4.fantom/fantom/src/launcher/dotnet.h
+++ /dev/null
@@ -1,14 +0,0 @@
-//
-// Copyright (c) 2006, Brian Frank and Andy Frank
-// Licensed under the Academic Free License version 3.0
-//
-// History:
-// 27 Dec 06 Brian Frank Creation
-//
-
-#ifndef _DOTNET_H
-#define _DOTNET_H
-
-extern int runDotnet();
-
-#endif
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/launcher/java.cpp b/com.xored.f4.fantom/fantom/src/launcher/java.cpp
deleted file mode 100755
index 9162d1b8..00000000
--- a/com.xored.f4.fantom/fantom/src/launcher/java.cpp
+++ /dev/null
@@ -1,247 +0,0 @@
-//
-// Copyright (c) 2006, Brian Frank and Andy Frank
-// Licensed under the Academic Free License version 3.0
-//
-// History:
-// 27 Dec 06 Brian Frank Creation
-//
-
-#include
-#include
-#include
-#include "props.h"
-#include "launcher.h"
-#include "utils.h"
-
-//////////////////////////////////////////////////////////////////////////
-// TypeDefs
-//////////////////////////////////////////////////////////////////////////
-
-typedef jint (JNICALL *CreateJavaVMFunc)(JavaVM **pvm, void **penv, void *vm_args);
-
-//////////////////////////////////////////////////////////////////////////
-// Globals
-//////////////////////////////////////////////////////////////////////////
-
-const int MAX_OPTIONS = 32; // max number of Java options
-JavaVMOption options[MAX_OPTIONS]; // Java options to pass to create VM
-char jvmPath[MAX_PATH]; // path to jvm.dll to dynamically load
-int nOptions; // Number of options
-JavaVM* vm; // VM created
-JNIEnv* env; // JNI environment
-
-//////////////////////////////////////////////////////////////////////////
-// Init Java VM
-//////////////////////////////////////////////////////////////////////////
-
-/**
- * Find the jvm.dll path to use by querying the registry.
- */
-int findJvmPath()
-{
- if (debug) printf("-- findJvmPath\n");
-
- // first see if explicitly specified in config.props
- const char* prop = getProp(sysProps, "java.jvm");
- if (prop != NULL)
- {
- if (debug) printf("-- java.jvm = %s\n", prop);
- sprintf(jvmPath, prop);
- return 0;
- }
-
- // query registry to get current Java version
- const char* jreKey = "SOFTWARE\\JavaSoft\\Java Runtime Environment";
- char curVer[MAX_PATH];
- if (readRegistry(jreKey, "CurrentVersion", curVer, sizeof(curVer))) return -1;
- if (debug) printf("-- registry query: CurrentVersion = %s\n", curVer);
-
- // use curVer to get default jvm.dll to use
- char jvmKey[MAX_PATH];
- sprintf(jvmKey, "%s\\%s", jreKey, curVer);
- if (readRegistry(jvmKey, "RuntimeLib", jvmPath, sizeof(jvmPath))) return -1;
- if (debug) printf("-- registry query: RuntimeLib = %s\n", jvmPath);
-
- return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Init Options
-//////////////////////////////////////////////////////////////////////////
-
-/**
- * Get the full list of options to pass to the Java VM which
- * are the required options set by the launcher, plus any additional
- * options configured in etc/sys/config.props.
- */
-int initOptions()
-{
- if (debug) printf("-- initOptions\n");
-
- // predefined classpath, include every jar file
- // found in lib/java/ext/win and lib/java/ext/win
- static char optClassPath[MAX_PATH*10];
- sprintf(optClassPath, "-Djava.class.path=%s\\lib\\java\\sys.jar", fanHome);
- options[nOptions++].optionString = optClassPath;
-
- // predefined fan.home
- static char optHome[MAX_PATH];
- sprintf(optHome, "-Dfan.home=%s", fanHome);
- options[nOptions++].optionString = optHome;
-
- // user specified options from config.props
- const char* prop = getProp(sysProps, "java.options", "");
- char* copy = new char[strlen(prop)+1];
- strcpy(copy, prop);
- char* tok = strtok(copy, " ");
- while (tok != NULL)
- {
- if (nOptions >= MAX_OPTIONS) break;
- options[nOptions++].optionString = tok;
- tok = strtok(NULL, " ");
- }
-
- // debug
- if (debug)
- {
- printf("-- options:\n");
- for (int i=0; iFindClass("java/lang/System");
- jmethodID getProp = env->GetStaticMethodID(sysClass, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;");
- jstring key = env->NewStringUTF("java.version");
- jstring jver = (jstring)env->CallStaticObjectMethod(sysClass, getProp, key);
- if (jver == NULL)
- return err("Cannot query java.version system property");
- const char* ver = env->GetStringUTFChars(jver, NULL);
- if (debug) printf("-- java.version = %s\n", ver);
-
- // parse major, minor
- const char* p = ver;
- int major = 0, minor = 0;
- while (*p != '.' && *p != '\0') { major = major*10 + (*p-'0'); p++; }
- p++;
- while (*p != '.' && *p != '\0') { minor = minor*10 + (*p-'0'); p++; }
- if (debug) printf("-- parsed = %d.%d\n", major, minor);
-
- // check that we are running 1.5
- if (major < 1 || minor < 5)
- return err("Fan requires Java 1.5 or greater (you have %s)", ver);
- if (debug) printf("-- version check ok\n");
-
- // cleanup
- env->ReleaseStringUTFChars(key, NULL);
- env->ReleaseStringUTFChars(jver, ver);
-
- return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Load Java
-//////////////////////////////////////////////////////////////////////////
-
-/**
- * Find and invoke the Java Fan runtime main.
- */
-int runJavaMain()
-{
- if (debug) printf("-- runJavaMain...\n");
-
- // figure out main
- char temp[256];
- sprintf(temp, "fanx/tools/%s", FAN_TOOL);
- const char* mainClassName = (const char*)temp;
-
- // find the main class
- if (debug) printf("-- find class %s...\n", mainClassName);
- jclass mainClass = env->FindClass(mainClassName);
- if (mainClass == NULL)
- return err("Cannot find Java main %s", mainClassName);
-
- // find the main method
- if (debug) printf("-- find method %s.main(String[])...\n", mainClassName);
- jmethodID mainMethod = env->GetStaticMethodID(mainClass, "main", "([Ljava/lang/String;)V");
- if (mainMethod == NULL)
- return err("Cannot find %s.main(String[])", mainClassName);
-
- // map C string args to Java string args
- if (debug) printf("-- c args to java args...\n");
- jstring jstr = env->NewStringUTF("");
- jobjectArray jargs = env->NewObjectArray(fanArgc, env->FindClass("java/lang/String"), jstr);
- for (int i=0; iSetObjectArrayElement(jargs, i, env->NewStringUTF(fanArgv[i]));
-
- // invoke main
- env->CallStaticVoidMethod(mainClass, mainMethod, jargs);
-
- return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Java Main
-//////////////////////////////////////////////////////////////////////////
-
-int runJava()
-{
- if (findJvmPath()) return -1;
- if (initOptions()) return -1;
- if (loadJava()) return -1;
- if (checkVersion()) return -1;
- if (runJavaMain()) return -1;
- return 0;
-}
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/launcher/java.h b/com.xored.f4.fantom/fantom/src/launcher/java.h
deleted file mode 100755
index 1975fb9e..00000000
--- a/com.xored.f4.fantom/fantom/src/launcher/java.h
+++ /dev/null
@@ -1,14 +0,0 @@
-//
-// Copyright (c) 2006, Brian Frank and Andy Frank
-// Licensed under the Academic Free License version 3.0
-//
-// History:
-// 27 Dec 06 Brian Frank Creation
-//
-
-#ifndef _JAVA_H
-#define _JAVA_H
-
-extern int runJava();
-
-#endif
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/launcher/launcher.cpp b/com.xored.f4.fantom/fantom/src/launcher/launcher.cpp
deleted file mode 100755
index 298a6d32..00000000
--- a/com.xored.f4.fantom/fantom/src/launcher/launcher.cpp
+++ /dev/null
@@ -1,279 +0,0 @@
-//
-// Copyright (c) 2006, Brian Frank and Andy Frank
-// Licensed under the Academic Free License version 3.0
-//
-// History:
-// 27 Dec 06 Brian Frank Creation
-//
-
-#include
-#include
-#include "launcher.h"
-#include "java.h"
-#include "dotnet.h"
-#include "utils.h"
-
-#ifndef FAN_TOOL
-#error "Must defined FAN_TOOL to be Fan, Fant, Fanp, etc"
-#endif
-
-//////////////////////////////////////////////////////////////////////////
-// TypeDefs
-//////////////////////////////////////////////////////////////////////////
-
-typedef enum { JavaRuntime, DotnetRuntime } Runtime;
-
-//////////////////////////////////////////////////////////////////////////
-// Globals
-//////////////////////////////////////////////////////////////////////////
-
-const char* LAUNCHER_VERSION = "1.0.50 2-Feb-10";
-
-bool debug; // is debug turned on
-char fanHome[MAX_PATH]; // dir path of fan installation
-Prop* sysProps; // {fanHome}\etc\sys\config.props
-int fanArgc; // argument count to pass to Fan runtime
-char** fanArgv; // argument values to pass to Fan runtime
-Runtime runtime; // runtime to use
-char* cmdLineRuntime = NULL; // runtime specified on cmd line
-
-
-//////////////////////////////////////////////////////////////////////////
-// Init
-//////////////////////////////////////////////////////////////////////////
-
-/**
- * Initialize the global variables for this process's environment.
- */
-int init(int argc, char** argv)
-{
- // debug controlled by environment variable or --v argument
- debug = getenv("fan_launcher_debug") != NULL;
- for (int i=1; i 0; len--) if (p[len] == '\\') { p[len] = '\0'; break; }
- for (; len > 0; len--) if (p[len] == '\\') { p[len] = '\0'; break; }
- strcpy(fanHome, p);
- if (debug) printf("-- fanHome = %s\n", fanHome);
-
- // parse etc/sys/config.props
- sprintf(p, "%s\\etc\\sys\\config.props", fanHome);
- sysProps = readProps(p);
- if (sysProps == NULL)
- printf("WARN: Cannot read config.props: \"%s\"", p);
-
- // debug props
- if (debug)
- {
- printf("-- config.props:\n");
- for (Prop* p = sysProps; p != NULL; p = p->next)
- printf("-- %s=%s\n", p->name, p->val);
- }
-
- return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Parse Arguments
-//////////////////////////////////////////////////////////////////////////
-
-/**
- * Parse arguments to initialize fanArgc and fanArgv, plus check for
- * arguments used by the launcher itself (prefixed via --). Note that
- * the --v debug is handled in init(), not this method.
- */
-int parseArgs(int argc, char** argv)
-{
- if (debug) printf("-- parseArgs\n");
-
- fanArgc = 0;
- fanArgv = new char*[argc];
-
-#ifdef FAN_MAIN
- fanArgv[fanArgc++] = FAN_MAIN;
-#endif
-
- for (int i=1; i= 3 && arg[0] == '-' && arg[1] == '-')
- {
- // --v (already handled in init)
- if (strcmp(arg, "--v") == 0)
- {
- continue;
- }
-
- // --Dname=value
- else if (arg[2] == 'D')
- {
- char* temp = new char[len];
- strcpy(temp, arg+3);
- char* name = strtok(temp, "=");
- char* val = strtok(NULL, "=");
- if (val != NULL)
- {
- sysProps = setProp(sysProps, name, val);
- if (debug) printf("-- override prop %s=%s\n", name, val);
- if (strcmp(name, "runtime") == 0) cmdLineRuntime = val;
- }
- continue;
- }
- }
-
- // pass thru to fan
- fanArgv[fanArgc++] = arg;
- }
-
- if (debug)
- {
- printf("-- fanArgs (%d)\n", fanArgc);
- for (int i=0; i "=" pairs separated by whitespace. The
- * scriptUri identifies a file on the local machine in URI format
- * of a Fan script file. The runtimeUri identifies the Fan home
- * directory of a Fan runtime installation.
- */
-int checkSubstitutes()
-{
- // we don't check for substitutes except when running the Fan
- // interpreter and we have at least one argument (which we
- // assume to be the target script being run)
- if (strcmp(FAN_TOOL, "Fan") != 0 || fanArgc < 1)
- return 0;
- const char* target = fanArgv[0];
-
- // check for system prop
- const char* prop = getProp(sysProps, "runtime.substitutes");
- if (prop == NULL) return 0;
-
- if (debug) printf("-- checkSubstitutes\n");
-
- // get the full path of the script as a Fan URI
- char targetUri[MAX_PATH];
- targetUri[0] = '/';
- if (GetFullPathName(target, sizeof(targetUri)-1, targetUri+1, NULL) == 0)
- return 0;
- for (int i=1; targetUri[i] != '\0'; ++i)
- if (targetUri[i] == '\\') targetUri[i] = '/';
- if (debug) printf("-- targetUri = %s\n", targetUri);
-
- // make copy of value on heap
- char* copy = new char[strlen(prop)+1];
- strcpy(copy, prop);
-
- // tokenize
- char* scriptUri = strtok(copy, " ");
- char* eq = strtok(NULL, " ");
- char* runtimeUri = strtok(NULL, " ");
- while (scriptUri != NULL && eq != NULL && runtimeUri != NULL)
- {
- if (debug) printf("-- %s = %s\n", scriptUri, runtimeUri);
-
- // sanity check
- if (strcmp(eq, "=") != 0)
- {
- err("Invalid format for sys prop \"runtime.substitutes\"\n");
- break;
- }
-
- // if we found a match update fan.home and break
- if (_stricmp(targetUri, scriptUri) == 0)
- {
- strcpy(fanHome, runtimeUri);
- if (debug) printf("-- substitute fan.home = %s\n", fanHome);
- break;
- }
-
- // move on to next token triple
- scriptUri = strtok(NULL, " ");
- eq = strtok(NULL, " ");
- runtimeUri = strtok(NULL, " ");
- }
-
- delete [] copy;
- return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Get Runtime
-//////////////////////////////////////////////////////////////////////////
-
-/**
- * Set the runtime variable with the runtime to use.
- */
-int getRuntime()
-{
- const char* rt = getProp(sysProps, "runtime", "java");
-
- if (getenv("fan_runtime") != NULL)
- rt = getenv("fan_runtime");
-
- if (cmdLineRuntime != NULL)
- rt = cmdLineRuntime;
-
- if (debug) printf("-- getRuntime = %s\n", rt);
-
- if (strcmp(rt, "java") == 0) runtime = JavaRuntime;
- else if (strcmp(rt, "dotnet") == 0) runtime = DotnetRuntime;
- else return err("Unknown runtime %s", rt);
-
- // force stub apps to always use the right runtime
- if (strcmp(FAN_TOOL, "Jstub") == 0) runtime = JavaRuntime;
- else if (strcmp(FAN_TOOL, "Nstub") == 0) runtime = DotnetRuntime;
-
- return 0;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Main
-//////////////////////////////////////////////////////////////////////////
-
-int main(int argc, char** argv)
-{
- if (init(argc, argv)) return -1;
- if (parseArgs(argc, argv)) return -1;
- if (checkSubstitutes()) return -1;
- if (getRuntime()) return -1;
- switch (runtime)
- {
- case JavaRuntime: return runJava();
- case DotnetRuntime: return runDotnet();
- default: return err("internal error in main");
- }
- return 0;
-}
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/launcher/launcher.h b/com.xored.f4.fantom/fantom/src/launcher/launcher.h
deleted file mode 100755
index 7fead98f..00000000
--- a/com.xored.f4.fantom/fantom/src/launcher/launcher.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Copyright (c) 2006, Brian Frank and Andy Frank
-// Licensed under the Academic Free License version 3.0
-//
-// History:
-// 27 Dec 06 Brian Frank Creation
-//
-
-#ifndef _LAUNCHER_H
-#define _LAUNCHER_H
-
-#include
-#include
-#include "props.h"
-
-extern bool debug; // is debug turned on
-extern char fanHome[MAX_PATH]; // dir path of fan installation
-extern Prop* sysProps; // {fanHome}/etc/sys/config.props
-extern int fanArgc; // argument count to pass to Fan runtime
-extern char** fanArgv; // argument values to pass to Fan runtime
-
-#endif
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/launcher/props.cpp b/com.xored.f4.fantom/fantom/src/launcher/props.cpp
deleted file mode 100755
index 423a97f7..00000000
--- a/com.xored.f4.fantom/fantom/src/launcher/props.cpp
+++ /dev/null
@@ -1,314 +0,0 @@
-//
-// Copyright (c) 2006, Brian Frank and Andy Frank
-// Licensed under the Academic Free License version 3.0
-//
-// History:
-// 27 Dec 06 Brian Frank Creation
-//
-
-#include
-#include
-#include
-#include "props.h"
-
-//////////////////////////////////////////////////////////////////////////
-// Char Stream
-//////////////////////////////////////////////////////////////////////////
-
-// push back for read
-int unread = 0;
-
-/**
- * Read next character from stream or return EOF
- */
-int readChar(FILE* fp)
-{
- if (unread != 0)
- {
- int c = unread;
- unread = 0;
- return c;
- }
- else
- {
- return fgetc(fp);
- }
-}
-
-/**
- * Pushback a character to reuse for next readChar()
- */
-void unreadChar(int ch)
-{
- assert(unread == 0);
- unread = ch;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Utils
-//////////////////////////////////////////////////////////////////////////
-
-/**
- * Convert a hexadecimal digit char into its numeric
- * value or return -1 on error.
- */
-int hex(int c)
-{
- if ('0' <= c && c <= '9') return c - '0';
- if ('a' <= c && c <= 'f') return c - 'a' + 10;
- if ('A' <= c && c <= 'F') return c - 'A' + 10;
- return -1;
-}
-
-/**
- * Return if specified character is whitespace.
- */
-bool isSpace(int c)
-{
- return c == ' ' || c == '\t';
-}
-
-/**
- * Given a pointer to a string of characters, trim the leading
- * and trailing whitespace and return a copy of the string from
- * heap memory.
- */
-char* makeTrimCopy(char* s, int num)
-{
- // trim leading/trailing whitespace
- int start = 0;
- int end = num;
- while (start < end) if (isSpace(s[start])) start++; else break;
- while (end > start) if (isSpace(s[end-1])) end--; else break;
- s[end] = '\0';
- s = s+start;
-
- // make copy on heap
- char* copy = new char[end-start+1];
- strcpy(copy, s);
- return copy;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Read
-//////////////////////////////////////////////////////////////////////////
-
-/**
- * Parse the specified props file according to the file format
- * specified by sys::InStream - this is pretty much a C port of
- * the Java implementation. Return a linked list of Props or if
- * error, then print error to stdout and return NULL.
- */
-Prop* readProps(const char* filename)
-{
- char name[512];
- char val[4096];
- int nameNum = 0, valNum = 0;
- bool inVal = false;
- int inBlockComment = 0;
- bool inEndOfLineComment = false;
- int c = -1, last = -1;
- int lineNum = 1;
- FILE* fp;
- Prop* head = NULL;
- Prop* tail = NULL;
-
- fp = fopen(filename, "r");
- if (fp == NULL)
- {
- printf("File not found [%s]\n", filename);
- return NULL;
- }
-
- for (;;)
- {
- last = c;
- c = readChar(fp);
- if (c == EOF) break;
-
- // end of line
- if (c == '\n' || c == '\r')
- {
- inEndOfLineComment = false;
- if (last == '\r' && c == '\n') continue;
- char* n = makeTrimCopy(name, nameNum);
- if (inVal)
- {
- char* v = makeTrimCopy(val, valNum);
-
- Prop* p = new Prop();
- p->name = n;
- p->val = v;
- p->next = NULL;
- if (head == NULL) { head = tail = p; }
- else { tail->next = p; tail = p; }
-
- inVal = false;
- nameNum = valNum = 0;
- }
- else if (strlen(n) > 0)
- {
- printf("Invalid name/value pair [%s:%d]\n", filename, lineNum);
- return NULL;
- }
- lineNum++;
- continue;
- }
-
- // if in comment
- if (inEndOfLineComment) continue;
-
- // block comment
- if (inBlockComment > 0)
- {
- if (last == '/' && c == '*') inBlockComment++;
- if (last == '*' && c == '/') inBlockComment--;
- continue;
- }
-
- // equal
- if (c == '=' && !inVal)
- {
- inVal = true;
- continue;
- }
-
- // comment
- if (c == '/')
- {
- int peek = readChar(fp);
- if (peek < 0) break;
- if (peek == '/') { inEndOfLineComment = true; continue; }
- if (peek == '*') { inBlockComment++; continue; }
- unreadChar(peek);
- }
-
- // escape or line continuation
- if (c == '\\')
- {
- int peek = readChar(fp);
- if (peek < 0) break;
- else if (peek == 'n') c = '\n';
- else if (peek == 'r') c = '\r';
- else if (peek == 't') c = '\t';
- else if (peek == '\\') c = '\\';
- else if (peek == '\r' || peek == '\n')
- {
- // line continuation
- lineNum++;
- if (peek == '\r')
- {
- peek = readChar(fp);
- if (peek != '\n') unreadChar(peek);
- }
- while (true)
- {
- peek = readChar(fp);
- if (peek == ' ' || peek == '\t') continue;
- unreadChar(peek);
- break;
- }
- continue;
- }
- else if (peek == 'u')
- {
- int n3 = hex(readChar(fp));
- int n2 = hex(readChar(fp));
- int n1 = hex(readChar(fp));
- int n0 = hex(readChar(fp));
- if (n3 < 0 || n2 < 0 || n1 < 0 || n0 < 0)
- {
- printf("Invalid hex value for \\uxxxx [%s:%d]\n", filename, lineNum);
- return NULL;
- }
- c = ((n3 << 12) | (n2 << 8) | (n1 << 4) | n0);
- }
- else
- {
- printf("Invalid escape sequence [%s:%d]\n", filename, lineNum);
- return NULL;
- }
- }
-
- // normal character
- if (inVal)
- {
- if (valNum+1 < sizeof(val)) val[valNum++] = c;
- }
- else
- {
- if (nameNum+1 < sizeof(name)) name[nameNum++] = c;
- }
- }
-
- char* n = makeTrimCopy(name, nameNum);
- if (inVal)
- {
- char* v = makeTrimCopy(val, valNum);
-
- Prop* p = new Prop();
- p->name = n;
- p->val = v;
- p->next = NULL;
- if (head == NULL) { head = tail = p; }
- else { tail->next = p; tail = p; }
- }
- else if (strlen(n) > 0)
- {
- printf("Invalid name/value pair [%s:%d]\n", filename, lineNum);
- return NULL;
- }
-
- return head;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Get
-//////////////////////////////////////////////////////////////////////////
-
-/**
- * Get a property from the linked list or return NULL if not found.
- */
-const char* getProp(Prop* props, const char* name) { return getProp(props, name, NULL); }
-
-/**
- * Get a property from the linked list or return def if not found.
- */
-const char* getProp(Prop* props, const char* name, const char* def)
-{
- for (Prop* p = props; p != NULL; p = p->next)
- if (strcmp(p->name, name) == 0)
- return p->val;
- return def;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Set
-//////////////////////////////////////////////////////////////////////////
-
-/**
- * Set a property in the linked list or add it if not found.
- */
-Prop* setProp(Prop* props, const char* name, const char* value)
-{
- Prop* last = NULL;
- for (Prop* p = props; p != NULL; p = p->next)
- {
- if (strcmp(p->name, name) == 0)
- {
- p->val = value;
- return props;
- }
- last = p;
- }
-
- Prop* p = new Prop();
- p->name = name;
- p->val = value;
- p->next = NULL;
-
- if (last == NULL) props = p;
- else last->next = p;
- return props;
-}
-
diff --git a/com.xored.f4.fantom/fantom/src/launcher/props.h b/com.xored.f4.fantom/fantom/src/launcher/props.h
deleted file mode 100755
index 78ffc8bc..00000000
--- a/com.xored.f4.fantom/fantom/src/launcher/props.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// Copyright (c) 2006, Brian Frank and Andy Frank
-// Licensed under the Academic Free License version 3.0
-//
-// History:
-// 27 Dec 06 Brian Frank Creation
-//
-
-#ifndef _PROPS_H
-#define _PROPS_H
-
-#include
-
-typedef struct Prop
-{
- const char* name;
- const char* val;
- struct Prop* next;
-} Prop;
-
-extern Prop* readProps(const char* filename);
-
-extern const char* getProp(Prop* props, const char* name);
-extern const char* getProp(Prop* props, const char* name, const char* def);
-
-extern Prop* setProp(Prop* props, const char* name, const char* value);
-
-#endif
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/launcher/utils.cpp b/com.xored.f4.fantom/fantom/src/launcher/utils.cpp
deleted file mode 100755
index 2b971d66..00000000
--- a/com.xored.f4.fantom/fantom/src/launcher/utils.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-//
-// Copyright (c) 2006, Brian Frank and Andy Frank
-// Licensed under the Academic Free License version 3.0
-//
-// History:
-// 28 Dec 06 Brian Frank Creation
-//
-
-#include
-#include
-#include "utils.h"
-
-//////////////////////////////////////////////////////////////////////////
-// Error Utils
-//////////////////////////////////////////////////////////////////////////
-
-/**
- * Print an error message and return -1.
- */
-int err(const char* msg, const char* arg1, const char* arg2)
-{
- printf("ERROR: ");
- printf(msg, arg1, arg2);
- printf("\n");
- return -1;
-}
-int err(const char* msg, const char* arg1) { return err(msg, arg1, "ignored"); }
-int err(const char* msg) { return err(msg, "ignored", "ignored"); }
-
-//////////////////////////////////////////////////////////////////////////
-// Registry Utils
-//////////////////////////////////////////////////////////////////////////
-
-/**
- * Read a registry string from HKEY_LOCAL_MACHINE.
- */
-int readRegistry(const char* subKey, char* name, char* buf, int bufLen)
-{
- // open key
- HKEY hKey;
- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
- return err("Cannot read registry: %s %s", subKey, name);
-
- // query
- int query = RegQueryValueEx(hKey, name, NULL, NULL, (LPBYTE)buf, (LPDWORD)&bufLen);
-
- // close
- RegCloseKey(hKey);
-
- // return result
- if (query != ERROR_SUCCESS)
- return err("Cannot read registry: %s %s", subKey, name);
-
- return 0;
-}
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/launcher/utils.h b/com.xored.f4.fantom/fantom/src/launcher/utils.h
deleted file mode 100755
index ef67cb3b..00000000
--- a/com.xored.f4.fantom/fantom/src/launcher/utils.h
+++ /dev/null
@@ -1,18 +0,0 @@
-//
-// Copyright (c) 2006, Brian Frank and Andy Frank
-// Licensed under the Academic Free License version 3.0
-//
-// History:
-// 28 Dec 06 Brian Frank Creation
-//
-
-#ifndef _UTILS_H
-#define _UTILS_H
-
-extern int err(const char* msg, const char* arg1, const char* arg2);
-extern int err(const char* msg, const char* arg1);
-extern int err(const char* msg);
-
-extern int readRegistry(const char* subKey, char* name, char* buf, int bufLen);
-
-#endif
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/math/build.fan b/com.xored.f4.fantom/fantom/src/math/build.fan
new file mode 100644
index 00000000..27dae908
--- /dev/null
+++ b/com.xored.f4.fantom/fantom/src/math/build.fan
@@ -0,0 +1,34 @@
+#! /usr/bin/env fan
+//
+// Copyright (c) 2020, Brian Frank and Andy Frank
+// Licensed under the Academic Free License version 3.0
+//
+// History:
+// 14 Aug 20 Matthew Giannini Creation
+//
+
+using build
+
+**
+** Build: math
+**
+class Build : BuildPod
+{
+ new make()
+ {
+ podName = "math"
+ summary = "Math utilities and functions"
+ meta = ["org.name": "Fantom",
+ "org.uri": "https://fantom.org/",
+ "proj.name": "Fantom Core",
+ "proj.uri": "https://fantom.org/",
+ "license.name": "Academic Free License 3.0",
+ "vcs.name": "Git",
+ "vcs.uri": "https://github.com/fantom-lang/fantom"]
+ depends = ["sys 1.0",]
+ srcDirs = [`fan/`, `test/`]
+ javaDirs = [`java/`]
+ docSrc = true
+ }
+}
+
diff --git a/com.xored.f4.fantom/fantom/src/math/fan/Math.fan b/com.xored.f4.fantom/fantom/src/math/fan/Math.fan
new file mode 100644
index 00000000..ceb610e8
--- /dev/null
+++ b/com.xored.f4.fantom/fantom/src/math/fan/Math.fan
@@ -0,0 +1,18 @@
+//
+// Copyright (c) 2020, Brian Frank and Andy Frank
+// Licensed under the Academic Free License version 3.0
+//
+// History:
+// 11 Aug 20 Matthew Giannini Creation
+//
+
+
+**
+** This mixin contains a set of utilities and functions for various math operations.
+**
+final class Math
+{
+ ** Create a new `Matrix` with the given number of rows and columns.
+ ** All elements of the matrix are initialized to zero.
+ static Matrix matrix(Int numRows, Int numCols) { MMatrix(numRows, numCols) }
+}
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/math/fan/Matrix.fan b/com.xored.f4.fantom/fantom/src/math/fan/Matrix.fan
new file mode 100644
index 00000000..6db57093
--- /dev/null
+++ b/com.xored.f4.fantom/fantom/src/math/fan/Matrix.fan
@@ -0,0 +1,93 @@
+//
+// Copyright (c) 2020, Brian Frank and Andy Frank
+// Licensed under the Academic Free License version 3.0
+//
+// History:
+// 11 Aug 20 Matthew Giannini Creation
+//
+
+**
+** Interface for matrix implementations. A matrix is a rectangular array of numbers.
+**
+mixin Matrix
+{
+ ** The number of rows in the matrix.
+ abstract Int numRows()
+
+ ** The number of columns in the matrix.
+ abstract Int numCols()
+
+ ** Return true if the matrix is square.
+ abstract Bool isSquare()
+
+ ** Get the element at 'A[i,j]', where 'i' is the row index, and 'j' is
+ ** column index.
+ abstract Float get(Int i, Int j)
+
+ ** Set the element at 'A[i,j]', where 'i' is the row index, and 'j' is
+ ** column index.
+ abstract This set(Int i, Int j, Float val)
+
+ ** Set every element in the matrix to the given val.
+ abstract This fill(Float val)
+
+ ** Get the transpose of the matrix.
+ abstract Matrix transpose()
+
+ ** Computes 'x * A'.
+ abstract This multScalar(Float x)
+
+ ** Computes 'A + B' and returns a new matrix.
+ @Operator abstract Matrix plus(Matrix b)
+
+ ** Computes 'A - B' and returns a new matrix.
+ @Operator abstract Matrix minus(Matrix b)
+
+ ** Computes 'A * B' and returns a new matrix.
+ @Operator abstract Matrix mult(Matrix b)
+
+ ** Compute the determinant of the matrix. The matrix must be square.
+ abstract Float determinant()
+
+ ** Compute the cofactor of the matrix. The matrix must be square.
+ abstract Matrix cofactor()
+
+ ** Compute the inverse of the matrix.
+ abstract Matrix inverse()
+}
+
+**
+** Native implementation of the Matrix mixin.
+**
+@NoDoc final native class MMatrix : Matrix
+{
+ new make(Int numRows, Int numCols)
+
+ override Int numRows()
+
+ override Int numCols()
+
+ override Bool isSquare()
+
+ override Float get(Int i, Int j)
+
+ override This set(Int i, Int j, Float val)
+
+ override This fill(Float val)
+
+ override Matrix transpose()
+
+ override This multScalar(Float x)
+
+ @Operator override Matrix plus(Matrix b)
+
+ @Operator override Matrix minus(Matrix b)
+
+ @Operator override Matrix mult(Matrix b)
+
+ override Float determinant()
+
+ override Matrix cofactor()
+
+ override Matrix inverse()
+}
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/math/java/MMatrix.java b/com.xored.f4.fantom/fantom/src/math/java/MMatrix.java
new file mode 100644
index 00000000..df0833c5
--- /dev/null
+++ b/com.xored.f4.fantom/fantom/src/math/java/MMatrix.java
@@ -0,0 +1,331 @@
+//
+// Copyright (c) 2020, Brian Frank and Andy Frank
+// Licensed under the Academic Free License version 3.0
+//
+// History:
+// 11 Aug 20 Matthew Giannini Creation
+//
+package fan.math;
+
+import fan.sys.*;
+import java.util.Arrays;
+
+public class MMatrix extends FanObj implements Matrix
+{
+
+//////////////////////////////////////////////////////////////////////////
+// Construction
+//////////////////////////////////////////////////////////////////////////
+
+ public static MMatrix make(final long numRows, final long numCols)
+ {
+ return new MMatrix(numRows, numCols, new double[(int)numRows * (int)numCols]);
+ }
+
+ private MMatrix(final long numRows, final long numCols, final double[] array)
+ {
+ if (numRows <= 0 || numCols <= 0)
+ throw ArgErr.make(String.format("Invalid matrix dimensions %d x %d", numRows, numCols));
+ if (array.length != numRows * numCols)
+ throw ArgErr.make("Invalid array");
+
+ this.numRows = numRows;
+ this.numCols = numCols;
+ this.array = array;
+ }
+
+//////////////////////////////////////////////////////////////////////////
+// Fields
+//////////////////////////////////////////////////////////////////////////
+
+ /* Model the storage as 1-dimensional array */
+ private double[] array;
+
+ private final long numRows;
+ private final long numCols;
+
+ /** Utility to get the matrix in a 2-dimensional array */
+ public double[][] toArray2D()
+ {
+ double[][] arr = new double[(int)numRows][(int)numCols];
+ for (int row = 0; row < numRows; ++row)
+ {
+ for (int col = 0; col < numCols; ++col)
+ {
+ arr[row] = new double[(int)numCols];
+ System.arraycopy(array, row * (int)numCols, arr[row], 0, (int)numCols);
+ }
+ }
+ return arr;
+ }
+
+//////////////////////////////////////////////////////////////////////////
+// Matrix
+//////////////////////////////////////////////////////////////////////////
+
+ public long numRows() { return numRows; }
+ public long numCols() { return numCols; }
+
+ public boolean isSquare() { return numRows == numCols; }
+
+ public double get(final long i, final long j)
+ {
+ return array[idx(i,j)];
+ }
+
+ public MMatrix set(final long i, final long j, double val)
+ {
+ array[idx(i,j)] = val;
+ return this;
+ }
+
+ public MMatrix fill(final double val)
+ {
+ Arrays.fill(array, val);
+ return this;
+ }
+
+ private int idx(final long i, final long j) { return (int)(i * numCols + j); }
+
+ public Matrix transpose()
+ {
+ MMatrix t = new MMatrix(numCols(), numRows(), new double[array.length]);
+ for (int r = 0; r < numRows; ++r)
+ {
+ for (int c = 0; c < numCols; ++c)
+ {
+ t.set(c, r, get(r, c));
+ }
+ }
+ return t;
+ }
+
+ public Matrix multScalar(final double x)
+ {
+ for (int i = 0; i < array.length; ++i) { array[i] *= x; }
+ return this;
+ }
+
+ public Matrix plus(final Matrix b)
+ {
+ checkDimsEq(b);
+ final MMatrix m = new MMatrix(numRows, numCols, new double[array.length]);
+ for (int i = 0; i < numRows; ++i)
+ {
+ for (int j = 0; j < numCols; ++j)
+ {
+ m.set(i, j, this.get(i,j) + b.get(i,j));
+ }
+ }
+ return m;
+ }
+
+ public Matrix minus(final Matrix b)
+ {
+ checkDimsEq(b);
+ final MMatrix m = new MMatrix(numRows, numCols, new double[array.length]);
+ for (int i = 0; i < numRows; ++i)
+ {
+ for (int j = 0; j < numCols; ++j)
+ {
+ m.set(i, j, this.get(i,j) - b.get(i,j));
+ }
+ }
+ return m;
+ }
+
+ public Matrix mult(final Matrix b)
+ {
+ if (this.numCols != b.numRows())
+ throw ArgErr.make(String.format("Matrix cols don't match rows: %d != %d", numCols, numRows));
+
+ final int numRows = (int)this.numRows();
+ final int numCols = (int)b.numCols();
+ final MMatrix m = new MMatrix(numRows, numCols, new double[numRows*numCols]);
+ for (int i = 0; i < numRows; ++i)
+ {
+ for (int j = 0; j < numCols; ++j)
+ {
+ double sum = 0d;
+ for (int k = 0; k < this.numCols; ++k) { sum += get(i,k) * b.get(k,j); }
+ m.set(i, j, sum);
+ }
+ }
+ return m;
+ }
+
+ public double determinant()
+ {
+ checkSquare();
+ if (numRows == 1) return get(0,0);
+ if (numRows == 2) return (get(0,0) * get(1,1)) - (get(0,1) * get(1,0));
+ return determinantLU();
+ }
+
+ public Matrix cofactor()
+ {
+ checkSquare();
+ final double[] m = new double[array.length];
+ for (int i=0; i java.lang.Math.abs(luColj[p])) p = i;
+ }
+ if (p != j)
+ {
+ for (int k=0; k Int[1, 2, 3]
+ **
+ L findNotNull()
+
**
** Return a new list containing the items for which c returns
** false. If c returns true for every item, then return an
@@ -478,6 +493,19 @@ final class List
**
Obj?[] map(|V item, Int index->Obj?| c)
+ **
+ ** Convenience for `map` and `findNotNull`. Each item is
+ ** mapped by the given function and if null is returned it is
+ ** excluded from the result. The resulting type is based on
+ ** on the return type of c but non-nullable. This method is
+ ** readonly safe.
+ **
+ ** Example:
+ ** list := [3, 4, 5]
+ ** list.mapIfNotNull |Int v->Int?| { v.isOdd ? 10+v : null } => [13, 15]
+ **
+ Obj[] mapNotNull(|V item, Int index->Obj?| c)
+
**
** This is a combination of `map` and `flatten`. Each item in
** this list is mapped to zero or more new items by the given function
@@ -492,6 +520,28 @@ final class List
**
Obj?[] flatMap(|V item, Int index->Obj?[]| c)
+ **
+ ** Group items into buckets keyed by the given function.
+ ** The result is a map of lists where the map keys are generated by
+ ** the given function. The map values are the items which share the
+ ** same key. The resulting map key type is determined by the
+ ** return type of c.
+ **
+ ** Example:
+ ** // group by string size
+ ** list := ["ape", "bear", "cat", "deer"]
+ ** list.groupBy |s->Int| { s.size } => [3:[ape, cat], 4:[bear, deer]]
+ **
+ // TODO add for 1.0.77
+ // Obj:L groupBy(|V item, Int index->Obj| c)
+
+ **
+ ** Group by into an existing map. This method shares the same
+ ** semantics as `groupBy` except it adds into the given map.
+ **
+ // TODO add for 1.0.77
+ // Obj:L groupByInto(Obj:L map, |V item, Int index->Obj| c)
+
**
** Reduce is used to iterate through every item in the list
** to reduce the list into a single value called the reduction.
diff --git a/com.xored.f4.fantom/fantom/src/sys/fan/Map.fan b/com.xored.f4.fantom/fantom/src/sys/fan/Map.fan
index 1a2710d0..2fd30065 100755
--- a/com.xored.f4.fantom/fantom/src/sys/fan/Map.fan
+++ b/com.xored.f4.fantom/fantom/src/sys/fan/Map.fan
@@ -122,10 +122,14 @@ final class Map
**
M add(K key, V val)
+ ** Deprecated - use addNotNull
+ @Deprecated { msg = "Use addNotNull" }
+ M addIfNotNull(K key, V? val)
+
**
** Call `add` if val is non-null otherwise do nothing. Return this.
**
- M addIfNotNull(K key, V? val)
+ M addNotNull(K key, V? val)
**
** Get the value for the specified key, or if it doesn't exist
@@ -292,6 +296,13 @@ final class Map
**
M findAll(|V val, K key->Bool| c)
+ **
+ ** Return a new map containing all the key/value pairs where
+ ** value is not null. If this map is `ordered` or `caseInsensitive`,
+ ** then the resulting map is too. This method is readonly safe.
+ **
+ M findNotNull()
+
**
** Return a new map containing the key/value pairs for which c
** returns false. If c returns true for every item, then return
@@ -346,6 +357,15 @@ final class Map
**
Obj:Obj? map(|V val, K key->Obj?| c)
+ **
+ ** Convenience for `map` and `findNotNull`. Each item is
+ ** mapped by the given function and if null is returned it is
+ ** excluded from the result. The resulting type is based on
+ ** on the return type of c but non-nullable. This method is
+ ** readonly safe.
+ **
+ Obj:Obj? mapNotNull(|V val, K key->Obj?| c)
+
//////////////////////////////////////////////////////////////////////////
// Readonly
//////////////////////////////////////////////////////////////////////////
diff --git a/com.xored.f4.fantom/fantom/src/sys/fan/NullErr.fan b/com.xored.f4.fantom/fantom/src/sys/fan/NullErr.fan
index e85d7f41..130dfafc 100755
--- a/com.xored.f4.fantom/fantom/src/sys/fan/NullErr.fan
+++ b/com.xored.f4.fantom/fantom/src/sys/fan/NullErr.fan
@@ -7,8 +7,10 @@
//
**
-** NullErr is a runtime exception raised when using a null reference
-** or when null is passed for a method argument which must be non-null.
+** NullErr indicates an attempt to dereference null. It is
+** often raised when attempting to access an instance field or method
+** on a null reference. It may also be thrown when a parameter is
+** expecting a non-nullable argument and null is passed.
**
const class NullErr : Err
{
diff --git a/com.xored.f4.fantom/fantom/src/sys/fan/Pod.fan b/com.xored.f4.fantom/fantom/src/sys/fan/Pod.fan
index 3b5ed0f9..45058ccf 100755
--- a/com.xored.f4.fantom/fantom/src/sys/fan/Pod.fan
+++ b/com.xored.f4.fantom/fantom/src/sys/fan/Pod.fan
@@ -165,4 +165,16 @@ final const class Pod
**
Str? locale(Str name, Str? def := "pod::name")
+ **
+ ** Expand a set of pods to include all their recurisve dependencies.
+ ** This method is does not order them; see `orderByDepends`.
+ **
+ static Pod[] flattenDepends(Pod[] pods)
+
+ **
+ ** Order a list of pods by their dependencies.
+ ** This method does not flatten dependencies - see `flattenDepends`.
+ **
+ static Pod[] orderByDepends(Pod[] pods)
+
}
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/sys/fan/ReadonlyErr.fan b/com.xored.f4.fantom/fantom/src/sys/fan/ReadonlyErr.fan
index 456a03ac..f79cf639 100755
--- a/com.xored.f4.fantom/fantom/src/sys/fan/ReadonlyErr.fan
+++ b/com.xored.f4.fantom/fantom/src/sys/fan/ReadonlyErr.fan
@@ -7,8 +7,8 @@
//
**
-** ReadonlyErr indicates an attempt to modify a readonly instance;
-** it is commonly used with List and Map.
+** ReadonlyErr indicates an attempt to modify a readonly instance.
+** It is commonly used with List and Map.
**
const class ReadonlyErr : Err
{
diff --git a/com.xored.f4.fantom/fantom/src/sys/fan/Unsafe.fan b/com.xored.f4.fantom/fantom/src/sys/fan/Unsafe.fan
index a0542f5b..ff12a727 100755
--- a/com.xored.f4.fantom/fantom/src/sys/fan/Unsafe.fan
+++ b/com.xored.f4.fantom/fantom/src/sys/fan/Unsafe.fan
@@ -7,8 +7,7 @@
//
**
-** Unsafe is used to wrap a non-const mutable objects so that
-** it can be passed as an immutable reference.
+** Unsafe wraps a mutable object as an immutable reference.
**
const final class Unsafe
{
diff --git a/com.xored.f4.fantom/fantom/src/sys/fan/Zip.fan b/com.xored.f4.fantom/fantom/src/sys/fan/Zip.fan
index 8c69bb1e..a940b0b0 100755
--- a/com.xored.f4.fantom/fantom/src/sys/fan/Zip.fan
+++ b/com.xored.f4.fantom/fantom/src/sys/fan/Zip.fan
@@ -101,12 +101,22 @@ final class Zip
** writing the entire zip file. Throw UnsupportedErr if zip is not writing
** to an output stream.
**
+ ** Next entry options:
+ ** - comment: Str entry comment
+ ** - crc: Int CRC-32 of the uncompressed data
+ ** - extra: Buf for extra bytes data field
+ ** - level: Int between 9 (best compression) to 0 (no compression)
+ ** - compressedSize: Int for compressed size of data
+ ** - uncompressedSize: Int for uncompressed size of data
+ **
+ ** NOTE: setting level to 0 sets method to STORE, else to DEFLATED.
+ **
** Examples:
** out := zip.writeNext(`/docs/test.txt`)
** out.writeLine("test")
** out.close
**
- OutStream writeNext(Uri path, DateTime modifyTime := DateTime.now)
+ OutStream writeNext(Uri path, DateTime modifyTime := DateTime.now, [Str:Obj?]? opts := null)
**
** Finish writing the contents of this zip file, but leave the underlying
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/BootEnv.java b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/BootEnv.java
index 0034a716..917453d3 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/BootEnv.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/BootEnv.java
@@ -81,16 +81,17 @@ private static String initHost()
{
try
{
- return java.net.InetAddress.getLocalHost().getHostName();
+ // use environment vars first to avoid DNS calls
+ String s;
+ s = System.getenv("FAN_HOSTNAME"); if (s != null) return s;
+ s = System.getenv("HOSTNAME"); if (s != null) return s;
}
catch (Throwable e) {}
try
{
- // fallbacks if DNS resolution fails
- String s;
- s = System.getenv("HOSTNAME"); if (s != null) return s;
- s = System.getenv("FAN_HOSTNAME"); if (s != null) return s;
+ // this will block if the network is down
+ return java.net.InetAddress.getLocalHost().getHostName();
}
catch (Throwable e) {}
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/Buf.java b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/Buf.java
index ebf29046..4cfd82e7 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/Buf.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/Buf.java
@@ -782,7 +782,7 @@ public byte[] constArray()
throw UnsupportedErr.make(typeof()+".constArray");
}
- /** Implements {@link Interop#toJava(Buf)} */
+ /** Implements {@link fanx.interop.Interop#toJava(Buf)} */
public ByteBuffer toByteBuffer()
{
throw UnsupportedErr.make(typeof()+".toByteBuffer");
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/DateTimeStr.java b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/DateTimeStr.java
index 89c1cfe1..bde99b1a 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/DateTimeStr.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/DateTimeStr.java
@@ -582,12 +582,14 @@ private int parseOptDigit()
private Month parseMon()
{
+ // TODO: this does not handle all the cases yet such as and fr "janv." and zh "10月"
StringBuilder s = new StringBuilder();
while (pos < str.length())
{
int ch = str.charAt(pos);
if ('a' <= ch && ch <= 'z') { s.append((char)ch); pos++; continue; }
if ('A' <= ch && ch <= 'Z') { s.append((char)FanInt.lower(ch)); pos++; continue; }
+ if (Character.isAlphabetic(ch)) { s.append((char)Character.toLowerCase(ch)); pos++; continue; }
break;
}
Month m = locale().monthByName(s.toString());
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/Env.java b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/Env.java
index 3c4ca158..b9131be2 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/Env.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/Env.java
@@ -215,9 +215,9 @@ public Class loadPodClass(Pod pod)
/**
* Load the Java class representations of a Fantom type:
- * - Fantom class => [class]
- * - Fantom mixin => [interface, body class]
- * - Fantom Err class => [class, val class]
+ * - Fantom class => [class]
+ * - Fantom mixin => [interface, body class]
+ * - Fantom Err class => [class, val class]
* Default implementation delegates to parent.
*/
public Class[] loadTypeClasses(ClassType t)
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanBool.java b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanBool.java
index 066c5c31..f6bd516e 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanBool.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanBool.java
@@ -12,8 +12,8 @@
/**
* FanBoolean defines the methods for sys::Bool:
- * sys::Bool => boolean primitive
- * sys::Bool? => java.lang.Boolean
+ * sys::Bool => boolean primitive
+ * sys::Bool? => java.lang.Boolean
*/
public final class FanBool
{
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanClassLoader.java b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanClassLoader.java
index eeb0c7bc..738bc93b 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanClassLoader.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanClassLoader.java
@@ -113,7 +113,7 @@ protected Class findClass(String name)
String s = e.toString();
if (s.contains("swt"))
{
- String msg = "cannot load SWT library; see http://fantom.org/doc/docTools/Setup.html#swt";
+ String msg = "cannot load SWT library; see https://fantom.org/doc/docTools/Setup.html#swt";
System.out.println("\nERROR: " + msg + "\n");
e = new NoClassDefFoundError(e.getMessage() + ": " + msg);
}
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanDecimal.java b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanDecimal.java
index e34921f8..5e88bf7a 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanDecimal.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanDecimal.java
@@ -81,7 +81,7 @@ public static Type typeof()
public static BigDecimal div(BigDecimal self, BigDecimal x)
{
// From https://github.com/groovy/groovy-core/blob/master/src/main/org/codehaus/groovy/runtime/typehandling/BigDecimalMath.java
- // as suggested by 'saltnlight5' in "Decimal operation failure?" discussion http://fantom.org/sidewalk/topic/1743
+ // as suggested by 'saltnlight5' in "Decimal operation failure?" discussion https://fantom.org/sidewalk/topic/1743
try
{
return self.divide(x);
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanFloat.java b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanFloat.java
index 9cd0774c..2f0f7be5 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanFloat.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanFloat.java
@@ -13,8 +13,8 @@
/**
* FanFloat defines the methods for sys::Float:
- * sys::Float => double primitive
- * sys::Float? => java.lang.Double
+ * sys::Float => double primitive
+ * sys::Float? => java.lang.Double
*/
public final class FanFloat
{
@@ -187,6 +187,13 @@ public static double max(double self, double that)
return that;
}
+ public static double clip(double self, double min, double max)
+ {
+ if (self < min) return min;
+ if (self > max) return max;
+ return self;
+ }
+
public static double ceil(double self)
{
return Math.ceil(self);
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanInt.java b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanInt.java
index e9dbdc3b..45972e16 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanInt.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FanInt.java
@@ -13,8 +13,8 @@
/**
* FanInt defines the methods for sys::Int
- * sys::Int => long primitive
- * sys::Int? => java.lang.Long
+ * sys::Int => long primitive
+ * sys::Int? => java.lang.Long
*/
public final class FanInt
{
@@ -169,6 +169,13 @@ public static long max(long self, long that)
return that;
}
+ public static long clip(long self, long min, long max)
+ {
+ if (self < min) return min;
+ if (self > max) return max;
+ return self;
+ }
+
public static long pow(long self, long pow)
{
if (pow < 0) throw ArgErr.make("pow < 0");
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/File.java b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/File.java
index d8fabd2f..7b0a18a1 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/File.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/File.java
@@ -140,6 +140,12 @@ public boolean isEmpty()
public boolean isHidden() { return false; }
+ public boolean isReadable() { return true; }
+
+ public boolean isWritable() { return false; }
+
+ public boolean isExecutable() { return false; }
+
public abstract String osPath();
public abstract File parent();
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FileStore.java b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FileStore.java
index 400e56b6..531d05a8 100644
--- a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FileStore.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/FileStore.java
@@ -19,9 +19,8 @@ public abstract class FileStore
protected static void make$() {}
- protected static void makeNew$(File self, Uri uri)
+ protected static void makeNew$(FileStore self)
{
- self.uri = uri;
}
public abstract Long totalSpace();
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/List.java b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/List.java
index c349ea5d..bab89f8a 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/List.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/List.java
@@ -185,22 +185,15 @@ public final Object getSafe(long index, Object def)
public final List getRange(Range r)
{
- try
- {
- int s = r.startIndex(size);
- int e = r.endIndex(size);
- int n = e - s + 1;
- if (n < 0) throw IndexErr.make(r);
+ int s = r.startIndex(size);
+ int e = r.endIndex(size);
+ int n = e - s + 1;
+ if (n < 0) throw IndexErr.make(r);
- List acc = new List(of, n);
- acc.size = n;
- System.arraycopy(values, s, acc.values, 0, n);
- return acc;
- }
- catch (ArrayIndexOutOfBoundsException e)
- {
- throw IndexErr.make(r);
- }
+ List acc = new List(of, n);
+ acc.size = n;
+ System.arraycopy(values, s, acc.values, 0, n);
+ return acc;
}
public final boolean contains(Object value)
@@ -400,7 +393,10 @@ public final List add(Object value)
return insert(size, value);
}
- public final List addIfNotNull(Object value)
+ // deprecated
+ public final List addIfNotNull(Object value) { return addNotNull(value); }
+
+ public final List addNotNull(Object value)
{
if (value == null) return this;
return add(value);
@@ -758,6 +754,18 @@ public final List findType(Type t)
return acc;
}
+ public final List findNotNull()
+ {
+ List acc = new List(of.toNonNullable(), size);
+ for (int i=0; i V = Foo
+ * ListType is the GenericType for Lists: Foo[] -> V = Foo
*/
public class ListType
extends GenericType
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/LocalFile.java b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/LocalFile.java
index 507157c0..3731b393 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/LocalFile.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/LocalFile.java
@@ -10,6 +10,7 @@
import java.io.Closeable;
import java.io.FileDescriptor;
import java.io.RandomAccessFile;
+import java.nio.file.Files;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
@@ -224,6 +225,12 @@ public void modified(DateTime time)
public boolean isHidden() { return file.isHidden(); }
+ public boolean isReadable() { return Files.isReadable(file.toPath()); }
+
+ public boolean isWritable() { return Files.isWritable(file.toPath()); }
+
+ public boolean isExecutable() { return Files.isExecutable(file.toPath()); }
+
public String osPath()
{
return file.getPath();
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/Map.java b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/Map.java
index ceaa4e79..7f4f3113 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/Map.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/Map.java
@@ -71,6 +71,11 @@ public final Type typeof()
return type;
}
+ MapType type()
+ {
+ return type;
+ }
+
//////////////////////////////////////////////////////////////////////////
// Methods
//////////////////////////////////////////////////////////////////////////
@@ -163,6 +168,11 @@ public final Map add(Object key, Object value)
}
public final Map addIfNotNull(Object key, Object value)
+ {
+ return addNotNull(key, value);
+ }
+
+ public final Map addNotNull(Object key, Object value)
{
if (value == null) return this;
return add(key, value);
@@ -417,6 +427,23 @@ public final Map findAll(Func f)
return acc;
}
+ public final Map findNotNull()
+ {
+ Map acc = new Map(type.k, type.v.toNonNullable());
+ if (this.ordered()) acc.ordered(true);
+ if (this.caseInsensitive()) acc.caseInsensitive(true);
+ Iterator it = pairsIterator();
+ while (it.hasNext())
+ {
+ Entry e = (Entry)it.next();
+ Object key = e.getKey();
+ Object val = e.getValue();
+ if (val != null)
+ acc.set(key, val);
+ }
+ return acc;
+ }
+
public final Map exclude(Func f)
{
Map acc = new Map(type);
@@ -495,6 +522,24 @@ public final Map map(Func f)
return acc;
}
+ public final Map mapNotNull(Func f)
+ {
+ Type r = f.returns();
+ if (r == Sys.VoidType) r = Sys.ObjType;
+ Map acc = new Map(type.k, r.toNonNullable());
+ if (this.ordered()) acc.ordered(true);
+ if (this.caseInsensitive()) acc.caseInsensitive(true);
+ Iterator it = pairsIterator();
+ while (it.hasNext())
+ {
+ Entry e = (Entry)it.next();
+ Object key = e.getKey();
+ Object val = e.getValue();
+ acc.addNotNull(key, f.call(val, key));
+ }
+ return acc;
+ }
+
//////////////////////////////////////////////////////////////////////////
// Conversion
//////////////////////////////////////////////////////////////////////////
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/MapType.java b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/MapType.java
index a7e5ec30..1511fc67 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/MapType.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/MapType.java
@@ -15,7 +15,7 @@
import fanx.emit.*;
/**
- * MapType is the GenericType for Maps: Foo:Bar -> K = Foo, V = Bar
+ * MapType is the GenericType for Maps: Foo:Bar -> K = Foo, V = Bar
*/
public class MapType
extends GenericType
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/Pod.java b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/Pod.java
index 27c0218c..64a578b1 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/Pod.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fan/sys/Pod.java
@@ -460,6 +460,54 @@ public final String locale(String key, String def)
return Env.cur().locale(this, key, def);
}
+ public static List flattenDepends(List pods)
+ {
+ Map acc = new Map(Sys.StrType, Sys.PodType);
+ for (int i=0; i.$Pod.
+ * FPodEmit translates FPod fcode to Java bytecode as a class called @{code <podName>.$Pod}.
* The pod class itself defines all the constants used by it's types.
*/
public class FPodEmit
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fanx/emit/FTypeEmit.java b/com.xored.f4.fantom/fantom/src/sys/java/fanx/emit/FTypeEmit.java
index 40157e2f..f27aec67 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fanx/emit/FTypeEmit.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fanx/emit/FTypeEmit.java
@@ -146,7 +146,12 @@ protected void emit(FField f)
{
if ((f.flags & FConst.Storage) != 0)
{
- FieldEmit fe = emitField(f.name, pod.typeRef(f.type).jsig(), jflags(f.flags));
+ // make const class once fields volatile
+ int jflags = jflags(f.flags);
+ if ((f.flags & FConst.Once) != 0 && (type.flags & FConst.Const) != 0)
+ jflags |= EmitConst.VOLATILE;
+
+ FieldEmit fe = emitField(f.name, pod.typeRef(f.type).jsig(), jflags);
FFacetEmit.emitField(fe, pod, f.attrs);
}
}
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fanx/fcode/FConst.java b/com.xored.f4.fantom/fantom/src/sys/java/fanx/fcode/FConst.java
index ebac310f..fd872e31 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fanx/fcode/FConst.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fanx/fcode/FConst.java
@@ -42,7 +42,8 @@ public interface FConst
public static final int Storage = 0x00010000;
public static final int Synthetic = 0x00020000;
public static final int Virtual = 0x00040000;
- public static final int FlagsMask = 0x0007ffff;
+ public static final int Once = 0x00080000;
+ public static final int FlagsMask = 0x000fffff;
//////////////////////////////////////////////////////////////////////////
// MethodVarFlags
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fanx/fcode/FTypeRef.java b/com.xored.f4.fantom/fantom/src/sys/java/fanx/fcode/FTypeRef.java
index 70930422..307da469 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fanx/fcode/FTypeRef.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fanx/fcode/FTypeRef.java
@@ -262,7 +262,7 @@ public boolean isPrimitiveIntLike()
/**
* If this type is represented as a Java primitive array, get the
- * stack type of component type: int[] -> INT.
+ * stack type of component type: int[] -> INT.
*/
public int arrayOfStackType()
{
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fanx/interop/Interop.java b/com.xored.f4.fantom/fantom/src/sys/java/fanx/interop/Interop.java
index 1aed8bd9..ecc798a9 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fanx/interop/Interop.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fanx/interop/Interop.java
@@ -45,7 +45,7 @@ public static Type toFan(Class cls)
/**
* Convert sys::Type to java.lang.Class. You
* can also access this functionality using the
- * trap operator "->toClass" on Type.
+ * trap operator "->toClass" on Type.
*/
public static Class toJava(Type type)
{
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fanx/tools/Fan.java b/com.xored.f4.fantom/fantom/src/sys/java/fanx/tools/Fan.java
index 600e4586..613c0773 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fanx/tools/Fan.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fanx/tools/Fan.java
@@ -218,7 +218,7 @@ static void cleanup()
static void version(String progName)
{
println(progName);
- println("Copyright (c) 2006-2019, Brian Frank and Andy Frank");
+ println("Copyright (c) 2006-2021, Brian Frank and Andy Frank");
println("Licensed under the Academic Free License version 3.0");
println("");
println("Java Runtime:");
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fanx/util/FanUtil.java b/com.xored.f4.fantom/fantom/src/sys/java/fanx/util/FanUtil.java
index 5551df49..4588c8ae 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fanx/util/FanUtil.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fanx/util/FanUtil.java
@@ -120,8 +120,8 @@ public static boolean isJavaRepresentation(Type t)
/**
* Given a Fantom qname, get the Java class name:
- * sys::Obj => java.lang.Object
- * foo::Bar => fan.foo.Bar
+ * sys::Obj => java.lang.Object
+ * foo::Bar => fan.foo.Bar
*/
public static String toJavaClassName(String podName, String typeName)
{
@@ -162,9 +162,9 @@ public static String toJavaClassName(String podName, String typeName)
/**
* Given a Fantom qname, get the Java implementation class name:
- * sys::Obj => fan.sys.FanObj
- * sys::Float => fan.sys.FanFloat
- * sys::Obj => fan.sys.FanObj
+ * sys::Obj => fan.sys.FanObj
+ * sys::Float => fan.sys.FanFloat
+ * sys::Obj => fan.sys.FanObj
*/
public static String toJavaImplClassName(String podName, String typeName)
{
@@ -205,8 +205,8 @@ public static String toJavaImplClassName(String podName, String typeName)
/**
* Given a Fantom qname, get the Java type signature:
- * sys::Obj => java/lang/Object
- * foo::Bar => fan/foo/Bar
+ * sys::Obj => java/lang/Object
+ * foo::Bar => fan/foo/Bar
*/
public static String toJavaTypeSig(String podName, String typeName, boolean nullable)
{
@@ -378,8 +378,8 @@ public static int toJavaStackType(Type t)
/**
* Given a Java type signature, return the implementation
* class signature for methods and fields:
- * java/lang/Object => fan/sys/FanObj
- * java/lang/Long => fan/sys/FanInt
+ * java/lang/Object => fan/sys/FanObj
+ * java/lang/Long => fan/sys/FanInt
* Anything returns itself.
*/
public static String toJavaImplSig(String jsig)
diff --git a/com.xored.f4.fantom/fantom/src/sys/java/fanx/util/TypeParser.java b/com.xored.f4.fantom/fantom/src/sys/java/fanx/util/TypeParser.java
index 5e28f7bc..c4bd72f9 100755
--- a/com.xored.f4.fantom/fantom/src/sys/java/fanx/util/TypeParser.java
+++ b/com.xored.f4.fantom/fantom/src/sys/java/fanx/util/TypeParser.java
@@ -18,7 +18,7 @@
* x::N
* x::V[]
* x::V[x::K]
- * |x::A, ... -> x::R|
+ * |x::A, ... -> x::R|
*/
public class TypeParser
{
diff --git a/com.xored.f4.fantom/fantom/src/sys/js/fan/Decimal.js b/com.xored.f4.fantom/fantom/src/sys/js/fan/Decimal.js
index 8831902f..2c9da7fd 100755
--- a/com.xored.f4.fantom/fantom/src/sys/js/fan/Decimal.js
+++ b/com.xored.f4.fantom/fantom/src/sys/js/fan/Decimal.js
@@ -101,4 +101,9 @@ fan.sys.Decimal.toLocale = function(self, pattern, locale)
//
// // route to common FanNum method
// return FanNum.toLocale(p, d, df);
+}
+
+fan.sys.Decimal.toStr = function(self)
+{
+ return fan.sys.Float.toStr(self);
}
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/sys/js/fan/Depend.js b/com.xored.f4.fantom/fantom/src/sys/js/fan/Depend.js
index 061a07fb..f07e3778 100755
--- a/com.xored.f4.fantom/fantom/src/sys/js/fan/Depend.js
+++ b/com.xored.f4.fantom/fantom/src/sys/js/fan/Depend.js
@@ -44,7 +44,7 @@ fan.sys.Depend.fromStr = function(str, checked)
fan.sys.Depend.prototype.equals = function(obj)
{
if (obj instanceof fan.sys.Depend)
- return this.toStr().equals(obj.toStr());
+ return this.toStr() == obj.toStr();
else
return false;
}
diff --git a/com.xored.f4.fantom/fantom/src/sys/js/fan/Float.js b/com.xored.f4.fantom/fantom/src/sys/js/fan/Float.js
index 931c6396..401a26b4 100755
--- a/com.xored.f4.fantom/fantom/src/sys/js/fan/Float.js
+++ b/com.xored.f4.fantom/fantom/src/sys/js/fan/Float.js
@@ -140,6 +140,14 @@ fan.sys.Float.round = function(self) { return fan.sys.Float.make(Math.round(self
fan.sys.Float.sqrt = function(self) { return fan.sys.Float.make(Math.sqrt(self)); }
fan.sys.Float.random = function() { return fan.sys.Float.make(Math.random()); }
+
+fan.sys.Float.clip = function(self, min, max)
+{
+ if (self < min) return min;
+ if (self > max) return max;
+ return self;
+}
+
// arithmetic
fan.sys.Float.plus = function(a,b) { return fan.sys.Float.make(a+b); }
fan.sys.Float.plusInt = function(a,b) { return fan.sys.Float.make(a+b); }
diff --git a/com.xored.f4.fantom/fantom/src/sys/js/fan/Int.js b/com.xored.f4.fantom/fantom/src/sys/js/fan/Int.js
index 2a38b084..9f75438d 100755
--- a/com.xored.f4.fantom/fantom/src/sys/js/fan/Int.js
+++ b/com.xored.f4.fantom/fantom/src/sys/js/fan/Int.js
@@ -89,6 +89,13 @@ fan.sys.Int.abs = function(self) { return self < 0 ? -self : self; }
fan.sys.Int.min = function(self, val) { return self < val ? self : val; }
fan.sys.Int.max = function(self, val) { return self > val ? self : val; }
+fan.sys.Int.clip = function(self, min, max)
+{
+ if (self < min) return min;
+ if (self > max) return max;
+ return self;
+}
+
fan.sys.Int.isEven = function(self) { return self % 2 == 0; }
fan.sys.Int.isOdd = function(self) { return self % 2 != 0; }
fan.sys.Int.isSpace = function(self) { return self == 32 || self == 9 || self == 10 || self == 13; }
@@ -380,4 +387,4 @@ fan.sys.Int.m_GB = 1024*1024*1024;
fan.sys.Int.localeIsUpper = function(self) { return fan.sys.Int.isUpper(self); }
fan.sys.Int.localeIsLower = function(self) { return fan.sys.Int.isLower(self); }
fan.sys.Int.localeUpper = function(self) { return fan.sys.Int.upper(self); }
-fan.sys.Int.localeLower = function(self) { return fan.sys.Int.lower(self); }
+fan.sys.Int.localeLower = function(self) { return fan.sys.Int.lower(self); }
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/sys/js/fan/List.js b/com.xored.f4.fantom/fantom/src/sys/js/fan/List.js
index ffe78d82..b68b3df9 100755
--- a/com.xored.f4.fantom/fantom/src/sys/js/fan/List.js
+++ b/com.xored.f4.fantom/fantom/src/sys/js/fan/List.js
@@ -272,6 +272,11 @@ fan.sys.List.prototype.add = function(value)
}
fan.sys.List.prototype.addIfNotNull = function(value)
+{
+ return this.addNotNull(value);
+}
+
+fan.sys.List.prototype.addNotNull = function(value)
{
if (value == null) return this;
return this.add(value);
@@ -575,6 +580,18 @@ fan.sys.List.prototype.findType = function(t)
return acc;
}
+fan.sys.List.prototype.findNotNull = function()
+{
+ var acc = fan.sys.List.make(this.m_of.toNonNullable());
+ for (var i=0; i 0)
- {
- params = fan.sys.MimeType.doParseParams(sub, semi+1);
- sub = fan.sys.Str.trim(sub.substring(0, semi));
- }
+ // check interned mime types
+ var mime = fan.sys.MimeType.byMime[s];
+ if (mime != null) return mime;
- var r = new fan.sys.MimeType();
- r.m_str = s;
- r.m_mediaType = fan.sys.Str.lower(media);
- r.m_subType = fan.sys.Str.lower(sub);
- r.m_params = params.ro();
- return r;
+ return fan.sys.MimeType.parseStr(s);
}
catch (err)
{
@@ -69,6 +35,29 @@ fan.sys.MimeType.fromStr = function(s, checked)
}
}
+fan.sys.MimeType.parseStr = function(s)
+{
+ var slash = s.indexOf('/');
+ if (slash < 0) throw ParseErr.make(s);
+ var media = s.substring(0, slash);
+ var sub = s.substring(slash+1, s.length);
+ var params = fan.sys.MimeType.emptyParams();
+
+ var semi = sub.indexOf(';');
+ if (semi > 0)
+ {
+ params = fan.sys.MimeType.doParseParams(sub, semi+1);
+ sub = fan.sys.Str.trim(sub.substring(0, semi));
+ }
+
+ var r = new fan.sys.MimeType();
+ r.m_str = s;
+ r.m_mediaType = fan.sys.Str.lower(media);
+ r.m_subType = fan.sys.Str.lower(sub);
+ r.m_params = params.ro();
+ return r;
+}
+
fan.sys.MimeType.parseParams = function(s, checked)
{
if (checked === undefined) checked = true;
@@ -194,23 +183,13 @@ fan.sys.MimeType.unescape = function(s)
// Extension
//////////////////////////////////////////////////////////////////////////
-fan.sys.MimeType.forExt = function(s)
+fan.sys.MimeType.forExt = function(ext)
{
- // TODO:FIXIT - we should really be loading this somehow from ext2mime.props
- if (s == null) return null;
+ if (ext == null) return null;
try
{
- s = s.toLowerCase();
- var m = null;
- switch (s)
- {
- case "png": m = "image/png"; break;
- case "txt": m = "text/plain; charset=utf-8"; break ;
- case "text": m = "text/plain; charset=utf-8"; break;
- }
- // TODO FIXIT
- //return (MimeType)Repo.readSymbolsCached(etcUri, Duration.oneMin).get(FanStr.lower(s));
- return fan.sys.MimeType.fromStr(m);
+ ext = ext.toLowerCase();
+ return fan.sys.MimeType.byExt[ext];
}
catch (err)
{
@@ -256,18 +235,16 @@ fan.sys.MimeType.prototype.mediaType = function() { return this.m_mediaType; }
fan.sys.MimeType.prototype.subType = function() { return this.m_subType; }
fan.sys.MimeType.prototype.params = function() { return this.m_params; }
-/*
fan.sys.MimeType.prototype.charset = function()
{
- String s = (String)params().get("charset");
- if (s == null) return Charset.utf8;
- return Charset.fromStr(s);
+ var s = this.params().get("charset");
+ if (s == null) return fan.sys.Charset.utf8();
+ return fan.sys.Charset.fromStr(s);
}
-*/
fan.sys.MimeType.prototype.noParams = function()
{
- if (this.params.isEmpty()) return this;
+ if (this.params().isEmpty()) return this;
return fan.sys.MimeType.fromStr(this.mediaType() + "/" + this.subType());
}
@@ -289,6 +266,28 @@ fan.sys.MimeType.emptyParams = function()
}
fan.sys.MimeType.emptyQuery = null;
+//////////////////////////////////////////////////////////////////////////
+// Cache - Populated by mime.js generated by MimeTool
+//////////////////////////////////////////////////////////////////////////
+
+fan.sys.MimeType.cache$ = function(ext, s)
+{
+ var mime = fan.sys.MimeType.parseStr(s);
+
+ // map ext to mime
+ fan.sys.MimeType.byExt[ext] = mime;
+
+ // map mime to its string encoding
+ fan.sys.MimeType.byMime[mime.toStr()] = mime;
+
+ // also map the no-parameter mime type by its string encoding
+ mime = mime.noParams();
+ fan.sys.MimeType.byMime[mime.toStr()] = mime;
+}
+
+fan.sys.MimeType.byExt = {}
+fan.sys.MimeType.byMime = {}
+
//////////////////////////////////////////////////////////////////////////
// Predefined
//////////////////////////////////////////////////////////////////////////
diff --git a/com.xored.f4.fantom/fantom/src/sys/js/fan/Type.js b/com.xored.f4.fantom/fantom/src/sys/js/fan/Type.js
index b22e04e4..54c3d9be 100755
--- a/com.xored.f4.fantom/fantom/src/sys/js/fan/Type.js
+++ b/com.xored.f4.fantom/fantom/src/sys/js/fan/Type.js
@@ -447,7 +447,13 @@ fan.sys.Type.prototype.doReflect = function()
var nameToIndex = {}; // String -> Int
// merge in base class and mixin classes
- for (var i=0; i> c / 4).toString(16);
+ });
+ }
+ return fan.sys.Uuid.fromStr(uuid);
}
fan.sys.Uuid.makeStr = function(a, b, c, d, e)
diff --git a/com.xored.f4.fantom/fantom/src/sys/js/fan/staticInit.js b/com.xored.f4.fantom/fantom/src/sys/js/fan/staticInit.js
index 0d8cbf99..643463c6 100755
--- a/com.xored.f4.fantom/fantom/src/sys/js/fan/staticInit.js
+++ b/com.xored.f4.fantom/fantom/src/sys/js/fan/staticInit.js
@@ -106,20 +106,6 @@ fan.sys.UriPodBase = "/pod/"; // TODO
//
fan.sys.Locale.m_en = fan.sys.Locale.fromStr("en")
-//
-// MimeType
-//
-fan.sys.MimeType.m_imagePng = fan.sys.MimeType.predefined("image", "png");
-fan.sys.MimeType.m_imageGif = fan.sys.MimeType.predefined("image", "gif");
-fan.sys.MimeType.m_imageJpeg = fan.sys.MimeType.predefined("image", "jpeg");
-fan.sys.MimeType.m_textPlain = fan.sys.MimeType.predefined("text", "plain");
-fan.sys.MimeType.m_textHtml = fan.sys.MimeType.predefined("text", "html");
-fan.sys.MimeType.m_textXml = fan.sys.MimeType.predefined("text", "xml");
-fan.sys.MimeType.m_textPlainUtf8 = fan.sys.MimeType.predefined("text", "plain", "charset=utf-8");
-fan.sys.MimeType.m_textHtmlUtf8 = fan.sys.MimeType.predefined("text", "html", "charset=utf-8");
-fan.sys.MimeType.m_textXmlUtf8 = fan.sys.MimeType.predefined("text", "xml", "charset=utf-8");
-fan.sys.MimeType.m_dir = fan.sys.MimeType.predefined("x-directory", "normal");
-
//
// LogLevel
//
diff --git a/com.xored.f4.fantom/fantom/src/sys/js/fanx/ObjDecoder.js b/com.xored.f4.fantom/fantom/src/sys/js/fanx/ObjDecoder.js
index 15ceba05..ce1b72c6 100755
--- a/com.xored.f4.fantom/fantom/src/sys/js/fanx/ObjDecoder.js
+++ b/com.xored.f4.fantom/fantom/src/sys/js/fanx/ObjDecoder.js
@@ -447,6 +447,10 @@ fanx_ObjDecoder.prototype.readMap = function(mapType, firstKey)
? fan.sys.Map.make(fan.sys.Obj.$type, fan.sys.Obj.$type.toNullable())
: fan.sys.Map.make(mapType);
+ // we don't encode whether the original map was ordered or not,
+ // so assume it was to ensure map is still ordered after decode
+ map.ordered$(true);
+
// finish first pair
this.consume(fanx_Token.COLON, "Expected ':'");
map.set(firstKey, this.$readObj(null, null, false));
@@ -545,7 +549,10 @@ fanx_ObjDecoder.prototype.readType = function(lbracket)
if (this.curt == fanx_Token.COLON)
{
this.consume();
- t = new fan.sys.MapType(t, this.readType());
+ var lbracket2 = this.curt == fanx_Token.LBRACKET;
+ if (lbracket2) this.consume();
+ t = new fan.sys.MapType(t, this.readType(lbracket2));
+ if (lbracket2) this.consume(fanx_Token.RBRACKET, "Expected closeing ']'");
}
while (this.curt == fanx_Token.LRBRACKET)
{
diff --git a/com.xored.f4.fantom/fantom/src/sys/locale/nl.props b/com.xored.f4.fantom/fantom/src/sys/locale/nl.props
index 995dac2c..2bfedaea 100755
--- a/com.xored.f4.fantom/fantom/src/sys/locale/nl.props
+++ b/com.xored.f4.fantom/fantom/src/sys/locale/nl.props
@@ -6,7 +6,7 @@ decimal=#.0##
int=#
numDecimal=,
numGrouping=.
-weekdayStart=sun
+weekdayStart=mon
janFull=januari
febFull=februari
marFull=maart
diff --git a/com.xored.f4.fantom/fantom/src/testCompiler/build.fan b/com.xored.f4.fantom/fantom/src/testCompiler/build.fan
index b920bc82..a387c124 100755
--- a/com.xored.f4.fantom/fantom/src/testCompiler/build.fan
+++ b/com.xored.f4.fantom/fantom/src/testCompiler/build.fan
@@ -19,12 +19,12 @@ class Build : BuildPod
podName = "testCompiler"
summary = "Test suite for compiler"
meta = ["org.name": "Fantom",
- "org.uri": "http://fantom.org/",
+ "org.uri": "https://fantom.org/",
"proj.name": "Fantom Core",
- "proj.uri": "http://fantom.org/",
+ "proj.uri": "https://fantom.org/",
"license.name": "Academic Free License 3.0",
- "vcs.name": "Mercurial",
- "vcs.uri": "https://bitbucket.org/fantom/fan-1.0/"]
+ "vcs.name": "Git",
+ "vcs.uri": "https://github.com/fantom-lang/fantom"]
depends = ["sys 1.0", "compiler 1.0", "concurrent 1.0"]
srcDirs = [`fan/`]
docApi = false
diff --git a/com.xored.f4.fantom/fantom/src/testCompiler/fan/CheckErrorsTest.fan b/com.xored.f4.fantom/fantom/src/testCompiler/fan/CheckErrorsTest.fan
index 685b2491..a23f6b6a 100755
--- a/com.xored.f4.fantom/fantom/src/testCompiler/fan/CheckErrorsTest.fan
+++ b/com.xored.f4.fantom/fantom/src/testCompiler/fan/CheckErrorsTest.fan
@@ -631,7 +631,7 @@ class CheckErrorsTest : CompilerTest
const [Num:Duration]? ok1 // ok
const [Num:Str[][]]? ok2 // ok
- once Int p() { return 3 } // 30
+ once Int p() { return 3 } // 30 ok now
}
class Bar {}
@@ -695,7 +695,9 @@ class CheckErrorsTest : CompilerTest
1, 7, "Const type 'Foo' cannot subclass non-const class 'Bar'", // further tests in testConstInheritance
22, 3, "Const type 'Foo' cannot contain non-const field 'j'",
+ /*
30, 3, "Const type 'Foo' cannot contain once method 'p'",
+ */
34, 1, "Non-const type 'Roo' cannot subclass const class 'Foo'",
35, 25, "Const type 'Boo' cannot contain non-const field 'x'",
@@ -1651,7 +1653,7 @@ class CheckErrorsTest : CompilerTest
6, 12, "Cannot use This as parameter type",
7, 12, "Cannot use Void as parameter type",
8, 12, "Cannot use This as parameter type",
- 9, 12, "Invalid type '|->sys::This|?'",
+ 9, 12, "Invalid return type 'sys::This' in func type of param 'a'",
10, 15, "'null' is not assignable to 'sys::Void?'",
10, 15, "Cannot use Void as local variable type",
10, 33, "Cannot call method on Void",
diff --git a/com.xored.f4.fantom/fantom/src/testCompiler/fan/CompilerTest.fan b/com.xored.f4.fantom/fantom/src/testCompiler/fan/CompilerTest.fan
index 645c49e7..da518f37 100755
--- a/com.xored.f4.fantom/fantom/src/testCompiler/fan/CompilerTest.fan
+++ b/com.xored.f4.fantom/fantom/src/testCompiler/fan/CompilerTest.fan
@@ -36,6 +36,7 @@ abstract class CompilerTest : Test
input.mode = CompilerInputMode.str
input.srcStr = src
input.srcStrLoc = Loc.make("Script")
+ //input.fcodeDump = true
f?.call(input)
compiler = Compiler.make(input)
diff --git a/com.xored.f4.fantom/fantom/src/testCompiler/fan/ItBlockTest.fan b/com.xored.f4.fantom/fantom/src/testCompiler/fan/ItBlockTest.fan
index 2eb144c4..9eaa967e 100755
--- a/com.xored.f4.fantom/fantom/src/testCompiler/fan/ItBlockTest.fan
+++ b/com.xored.f4.fantom/fantom/src/testCompiler/fan/ItBlockTest.fan
@@ -412,6 +412,62 @@ class ItBlockTest : CompilerTest
verifyEq(obj->m06, Obj?["G", "H", "I"])
}
+//////////////////////////////////////////////////////////////////////////
+// This Params (allow This to be used func parameters in method params)
+//////////////////////////////////////////////////////////////////////////
+
+ Void testThisParams()
+ {
+ compile(
+ """class Acme
+ {
+ Obj c1() { x1 {} }
+ Obj c2() { x2 { this } }
+ Obj c3() { x3 |t, s| { t.s + "," + s } }
+ Obj c4() { x4 |s, t| { s + "," + t.s } }
+ Obj c5() { x5 |a, b| { a.s + "," + b.s } }
+ Obj c6() { x5 |a, b| { a.s + "," + b.s } }
+
+ Obj x1(|This| f) { f(this); return this }
+ Obj x2(|This->Obj| f) { return f(this) }
+ Obj x3(|This, Str->Obj| f) { f(this, "foo") }
+ Obj x4(|Str, This->Str| f) { f("foo", this) }
+ Obj x5(|This, This->Str| f) { f(this, this) }
+ Obj x6(|This?, This?->Str| f) { f(this, this) }
+
+ Str s() { typeof.name }
+ }""")
+
+ obj := pod.types.first.make
+ verifySame(obj->c1, obj)
+ verifySame(obj->c2, obj)
+ verifyEq(obj->c3, "Acme,foo")
+ verifyEq(obj->c4, "foo,Acme")
+ verifyEq(obj->c5, "Acme,Acme")
+ verifyEq(obj->c6, "Acme,Acme")
+ }
+
+ Void testThisParamsErr()
+ {
+ verifyErrors(
+ "class Foo
+ {
+ Void x3(|->This| a) {}
+ Void x4(|->This?| b) {}
+ Void x5(|Void->Str| c) {}
+ Void x6(|Str,Void->Str| d) {}
+ Void x7(|Str,Void?->Str| e) {}
+ }
+ ",
+ [
+ 3, 11, "Invalid return type 'sys::This' in func type of param 'a'",
+ 4, 11, "Invalid return type 'sys::This?' in func type of param 'b'",
+ 5, 11, "Invalid param type 'sys::Void' in func type of param 'c'",
+ 6, 11, "Invalid param type 'sys::Void' in func type of param 'd'",
+ 7, 11, "Invalid param type 'sys::Void?' in func type of param 'e'",
+ ])
+ }
+
//////////////////////////////////////////////////////////////////////////
// ConstErr
//////////////////////////////////////////////////////////////////////////
diff --git a/com.xored.f4.fantom/fantom/src/testCompiler/fan/MiscTest.fan b/com.xored.f4.fantom/fantom/src/testCompiler/fan/MiscTest.fan
index 84f1cfce..3db1b1ac 100755
--- a/com.xored.f4.fantom/fantom/src/testCompiler/fan/MiscTest.fan
+++ b/com.xored.f4.fantom/fantom/src/testCompiler/fan/MiscTest.fan
@@ -604,6 +604,34 @@ class MiscTest : CompilerTest
])
}
+//////////////////////////////////////////////////////////////////////////
+// Once Const
+//////////////////////////////////////////////////////////////////////////
+
+ Void testOnceConst()
+ {
+ compile(
+ "const class A
+ {
+ virtual once Str x() { Int.random.toStr }
+ once DateTime bad() { throw Err.make }
+ }
+
+ const class B : A
+ {
+ override Str x() { Int.random.toStr }
+ }
+ ")
+
+ a := pod.type("A").make
+ b := pod.type("B").make
+ verifySame(a->x, a->x)
+ verifyNotSame(b->x, b->x)
+ verifyErr(Err#) { a->bad }
+ verifyErr(Err#) { a->bad }
+ verifyErr(Err#) { a->bad }
+ }
+
//////////////////////////////////////////////////////////////////////////
// Func Types
//////////////////////////////////////////////////////////////////////////
diff --git a/com.xored.f4.fantom/fantom/src/testDomkit/build.fan b/com.xored.f4.fantom/fantom/src/testDomkit/build.fan
index 066229d4..5923e497 100644
--- a/com.xored.f4.fantom/fantom/src/testDomkit/build.fan
+++ b/com.xored.f4.fantom/fantom/src/testDomkit/build.fan
@@ -19,12 +19,12 @@ class Build : BuildPod
podName = "testDomkit"
summary = "Domkit Test Framework"
meta = ["org.name": "Fantom",
- "org.uri": "http://fantom.org/",
+ "org.uri": "https://fantom.org/",
"proj.name": "Fantom Core",
- "proj.uri": "http://fantom.org/",
+ "proj.uri": "https://fantom.org/",
"license.name": "Academic Free License 3.0",
- "vcs.name": "Mercurial",
- "vcs.uri": "https://bitbucket.org/fantom/fan-1.0/"]
+ "vcs.name": "Git",
+ "vcs.uri": "https://github.com/fantom-lang/fantom"]
depends = ["sys 1.0",
"concurrent 1.0",
"util 1.0",
diff --git a/com.xored.f4.fantom/fantom/src/testDomkit/fan/Main.fan b/com.xored.f4.fantom/fantom/src/testDomkit/fan/Main.fan
index d7537ca6..0d92e0cb 100644
--- a/com.xored.f4.fantom/fantom/src/testDomkit/fan/Main.fan
+++ b/com.xored.f4.fantom/fantom/src/testDomkit/fan/Main.fan
@@ -32,10 +32,20 @@ class Main : AbstractMain
const class DomkitTestMod : WebMod
{
- new make(|This| f) { f(this) }
+ new make(|This| f)
+ {
+ f(this)
+ pods := [typeof.pod]
+ this.jsPack = FilePack(FilePack.toAppJsFiles(pods))
+ this.cssPack = FilePack(FilePack.toAppCssFiles(pods))
+ }
const Bool useSampleCss := false
+ const FilePack jsPack
+
+ const FilePack cssPack
+
override Void onService()
{
n := req.modRel.path.first
@@ -43,9 +53,9 @@ const class DomkitTestMod : WebMod
{
case null: onIndex
case "test": onTest
+ case "app.js": jsPack.onService
+ case "app.css": cssPack.onService
case "pod": onPod
- case "units.js": onUnits
- case "tz.js": onTz
default: res.sendErr(404)
}
}
@@ -84,17 +94,8 @@ const class DomkitTestMod : WebMod
out.html
out.head
.title.w("Domkit Test").titleEnd
- .includeCss(`/pod/domkit/res/css/domkit.css`)
- .includeJs(`/pod/sys/sys.js`)
- .includeJs(`/tz.js`)
- .includeJs(`/units.js`)
- .includeJs(`/pod/util/util.js`)
- .includeJs(`/pod/concurrent/concurrent.js`)
- .includeJs(`/pod/graphics/graphics.js`)
- .includeJs(`/pod/web/web.js`)
- .includeJs(`/pod/dom/dom.js`)
- .includeJs(`/pod/domkit/domkit.js`)
- .includeJs(`/pod/testDomkit/testDomkit.js`)
+ .includeCss(`/app.css`)
+ .includeJs(`/app.js`)
.style.w(
"html { height: 100%; }
body {
@@ -130,18 +131,6 @@ const class DomkitTestMod : WebMod
FileWeblet(file).onService
}
- Void onUnits()
- {
- res.headers["Content-Type"] = "text/javascript; charset=utf-8"
- JsUnitDatabase().write(res.out)
- }
-
- Void onTz()
- {
- res.headers["Content-Type"] = "text/javascript; charset=utf-8"
- res.out.writeBuf((Env.cur.homeDir + `etc/sys/tz.js`).readAllBuf)
- }
-
const Str sampleCss :=
""".domkit-sel {
background-color: #dcdcdc !important;
diff --git a/com.xored.f4.fantom/fantom/src/testJava/build.fan b/com.xored.f4.fantom/fantom/src/testJava/build.fan
index 1adf7500..1989442a 100755
--- a/com.xored.f4.fantom/fantom/src/testJava/build.fan
+++ b/com.xored.f4.fantom/fantom/src/testJava/build.fan
@@ -19,12 +19,12 @@ class Build : BuildPod
podName = "testJava"
summary = "Test suite for Java FFI compiler plugin"
meta = ["org.name": "Fantom",
- "org.uri": "http://fantom.org/",
+ "org.uri": "https://fantom.org/",
"proj.name": "Fantom Core",
- "proj.uri": "http://fantom.org/",
+ "proj.uri": "https://fantom.org/",
"license.name": "Academic Free License 3.0",
- "vcs.name": "Mercurial",
- "vcs.uri": "https://bitbucket.org/fantom/fan-1.0/"]
+ "vcs.name": "Git",
+ "vcs.uri": "https://github.com/fantom-lang/fantom"]
depends = ["sys 1.0", "compiler 1.0", "compilerJava 1.0", "testCompiler 1.0"]
srcDirs = [`fan/`]
docApi = false
diff --git a/com.xored.f4.fantom/fantom/src/testNative/build.fan b/com.xored.f4.fantom/fantom/src/testNative/build.fan
index ae1fe848..ad8810cf 100755
--- a/com.xored.f4.fantom/fantom/src/testNative/build.fan
+++ b/com.xored.f4.fantom/fantom/src/testNative/build.fan
@@ -19,12 +19,12 @@ class Build : BuildPod
podName = "testNative"
summary = "Sys natives test suite"
meta = ["org.name": "Fantom",
- "org.uri": "http://fantom.org/",
+ "org.uri": "https://fantom.org/",
"proj.name": "Fantom Core",
- "proj.uri": "http://fantom.org/",
+ "proj.uri": "https://fantom.org/",
"license.name": "Academic Free License 3.0",
- "vcs.name": "Mercurial",
- "vcs.uri": "https://bitbucket.org/fantom/fan-1.0/"]
+ "vcs.name": "Git",
+ "vcs.uri": "https://github.com/fantom-lang/fantom"]
depends = ["sys 1.0"]
srcDirs = [`fan/`]
javaDirs = [`java/`]
diff --git a/com.xored.f4.fantom/fantom/src/testSys/build.fan b/com.xored.f4.fantom/fantom/src/testSys/build.fan
index bef6d2eb..9fa0b180 100755
--- a/com.xored.f4.fantom/fantom/src/testSys/build.fan
+++ b/com.xored.f4.fantom/fantom/src/testSys/build.fan
@@ -19,12 +19,12 @@ class Build : BuildPod
podName = "testSys"
summary = "System and runtime test suite"
meta = ["org.name": "Fantom",
- "org.uri": "http://fantom.org/",
+ "org.uri": "https://fantom.org/",
"proj.name": "Fantom Core",
- "proj.uri": "http://fantom.org/",
+ "proj.uri": "https://fantom.org/",
"license.name": "Academic Free License 3.0",
- "vcs.name": "Mercurial",
- "vcs.uri": "https://bitbucket.org/fantom/fan-1.0/",
+ "vcs.name": "Git",
+ "vcs.uri": "https://github.com/fantom-lang/fantom",
"testSys.foo":"got\n it \u0123"]
depends = ["sys 1.0", "concurrent 1.0"]
index = [
diff --git a/com.xored.f4.fantom/fantom/src/testSys/fan/DateTimeTest.fan b/com.xored.f4.fantom/fantom/src/testSys/fan/DateTimeTest.fan
index 73f796f0..aa93023e 100755
--- a/com.xored.f4.fantom/fantom/src/testSys/fan/DateTimeTest.fan
+++ b/com.xored.f4.fantom/fantom/src/testSys/fan/DateTimeTest.fan
@@ -1232,6 +1232,23 @@ class DateTimeTest : Test
verifyNull(Date.fromLocale("2-nomonth-1999", "D-MMMM-YYYY", false))
verifyErr(ParseErr#) { Date.fromLocale("xyz", "YY-MM-DD") }
verifyErr(ParseErr#) { Date.fromLocale("99-xxx-02", "YY-MMM-DD", true) }
+
+ // test different months for common locales
+ // note: fr doesn't work because the months have period after abbrevation
+ // TODO: This does not handle all the cases yet such as and fr "janv." and zh "10月";
+ // need to add fr, zh, ru, ja
+ ["de", "nl", "pt", "es", "it", "fa", "he"].each |localeStr|
+ {
+ Locale(localeStr).use
+ {
+ Month.vals.each |m|
+ {
+ dm := Date(2021, m, 01)
+ s := dm.toLocale("DD MMM YYYY")
+ verifyEq(Date.fromLocale(s, "DD MMM YYYY"), dm)
+ }
+ }
+ }
}
Void verifyDateLocale(Date d, Str pattern, Str expected)
@@ -1769,4 +1786,17 @@ class DateTimeTest : Test
}
}
+//////////////////////////////////////////////////////////////////////////
+// Js Float Drift
+//////////////////////////////////////////////////////////////////////////
+
+ Void testJsFloatDrift()
+ {
+ a := DateTime("2021-01-22T10:18:53.375+01:00 Madrid")
+ b := a.toTimeZone(TimeZone("New_York"))
+ verifyEq(a.ticks, b.ticks)
+ verifyEq(a.toStr, "2021-01-22T10:18:53.375+01:00 Madrid")
+ verifyEq(b.toStr, "2021-01-22T04:18:53.375-05:00 New_York")
+ }
+
}
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/testSys/fan/FloatTest.fan b/com.xored.f4.fantom/fantom/src/testSys/fan/FloatTest.fan
index c534f76f..28a5379f 100755
--- a/com.xored.f4.fantom/fantom/src/testSys/fan/FloatTest.fan
+++ b/com.xored.f4.fantom/fantom/src/testSys/fan/FloatTest.fan
@@ -364,6 +364,15 @@ class FloatTest : Test
verifyEq(0f.max(1f), 1f)
verifyEq((-99.0f).max(-6666.0f), -99.0f)
+ // clip
+ verifyEq((3f).clip(0f, 100f), 3f)
+ verifyEq((-3f).clip(0f, 100f), 0f)
+ verifyEq((0f).clip(0f, 100f), 0f)
+ verifyEq((99f).clip(0f, 100f), 99f)
+ verifyEq((100f).clip(0f, 100f), 100f)
+ verifyEq((100.7f).clip(0f, 100f), 100f)
+ verifyEq((890.7f).clip(0f, 100f), 100f)
+
// ceil
verifyEq(88f.ceil, 88f)
verifyEq(6.335f.ceil, 7f)
diff --git a/com.xored.f4.fantom/fantom/src/testSys/fan/IntTest.fan b/com.xored.f4.fantom/fantom/src/testSys/fan/IntTest.fan
index b51cc224..9e636cb8 100755
--- a/com.xored.f4.fantom/fantom/src/testSys/fan/IntTest.fan
+++ b/com.xored.f4.fantom/fantom/src/testSys/fan/IntTest.fan
@@ -320,6 +320,14 @@ class IntTest : Test
verifyEq((-99).max(-6666), -99)
verifyEq('a'.max(' '), 'a')
+ verifyEq(3.clip(0, 100), 3)
+ verifyEq(3.clip(4, 4), 4)
+ verifyEq((-3).clip(0, 100), 0)
+ verifyEq(0.clip(0, 100), 0)
+ verifyEq(100.clip(0, 100), 100)
+ verifyEq(101.clip(0, 100), 100)
+ verifyEq(201.clip(0, 100), 100)
+
verifyEq(5.pow(0), 1)
verifyEq(5.pow(1), 5)
verifyEq(5.pow(2), 25)
@@ -773,4 +781,4 @@ class IntTest : Test
const Bool js := Env.cur.runtime == "js"
-}
+}
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/testSys/fan/ListTest.fan b/com.xored.f4.fantom/fantom/src/testSys/fan/ListTest.fan
index cf9fbe35..e8cb48ac 100755
--- a/com.xored.f4.fantom/fantom/src/testSys/fan/ListTest.fan
+++ b/com.xored.f4.fantom/fantom/src/testSys/fan/ListTest.fan
@@ -372,17 +372,17 @@ class ListTest : Test
}
//////////////////////////////////////////////////////////////////////////
-// AddIfNotNull
+// AddNotNull
//////////////////////////////////////////////////////////////////////////
- Void testAddIfNotNull()
+ Void testAddNotNull()
{
x := Str[,]
- verifySame(x.addIfNotNull("a"), x)
+ verifySame(x.addNotNull("a"), x)
verifyEq(x, ["a"])
- verifySame(x.addIfNotNull(null), x)
+ verifySame(x.addNotNull(null), x)
verifyEq(x, ["a"])
- verifySame(x.addIfNotNull("b"), x)
+ verifySame(x.addNotNull("b"), x)
verifyEq(x, ["a", "b"])
}
@@ -504,10 +504,10 @@ class ListTest : Test
}
//////////////////////////////////////////////////////////////////////////
-// Slicing
+// GetRange
//////////////////////////////////////////////////////////////////////////
- Void testSlicing()
+ Void testGetRange()
{
/* Ruby
irb(main):001:0> a = [0, 1, 2, 3] => [0, 1, 2, 3]
@@ -537,36 +537,36 @@ class ListTest : Test
list := [0, 1, 2, 3]
- verifyEq(list[0..3], [0, 1, 2, 3])
- verifyEq(list[0..2], [0, 1, 2])
- verifyEq(list[0..1], [0, 1])
- verifyEq(list[0..0], [0])
- verifyEq(list[0..<0], Int[,])
- verifyEq(list[0..<1], [0])
- verifyEq(list[0..<2], [0, 1])
- verifyEq(list[0..<3], [0, 1, 2])
- verifyEq(list[0..<4], [0, 1, 2, 3])
- verifyEq(list[1..3], [1, 2, 3])
- verifyEq(list[1..1], [1])
- verifyEq(list[1..-1], [1, 2, 3])
- verifyEq(list[1..-2], [1, 2])
- verifyEq(list[1..-3], [1])
- verifyEq(list[1..-4], Int[,])
- verifyEq(list[1..<-1], [1, 2])
- verifyEq(list[1..<-2], [1])
- verifyEq(list[1..<-3], Int[,])
- verifyEq(list[-3..-1], [1, 2, 3])
- verifyEq(list[-3..-2], [1, 2])
- verifyEq(list[-3..-3], [1])
- verifyEq(list[4..-1], Int[,])
+ verifyGetRange(list, 0..3, [0, 1, 2, 3])
+ verifyGetRange(list, 0..2, [0, 1, 2])
+ verifyGetRange(list, 0..1, [0, 1])
+ verifyGetRange(list, 0..0, [0])
+ verifyGetRange(list, 0..<0, Int[,])
+ verifyGetRange(list, 0..<1, [0])
+ verifyGetRange(list, 0..<2, [0, 1])
+ verifyGetRange(list, 0..<3, [0, 1, 2])
+ verifyGetRange(list, 0..<4, [0, 1, 2, 3])
+ verifyGetRange(list, 1..3, [1, 2, 3])
+ verifyGetRange(list, 1..1, [1])
+ verifyGetRange(list, 1..-1, [1, 2, 3])
+ verifyGetRange(list, 1..-2, [1, 2])
+ verifyGetRange(list, 1..-3, [1])
+ verifyGetRange(list, 1..-4, Int[,])
+ verifyGetRange(list, 1..<-1, [1, 2])
+ verifyGetRange(list, 1..<-2, [1])
+ verifyGetRange(list, 1..<-3, Int[,])
+ verifyGetRange(list, -3..-1, [1, 2, 3])
+ verifyGetRange(list, -3..-2, [1, 2])
+ verifyGetRange(list, -3..-3, [1])
+ verifyGetRange(list, 4..-1, Int[,])
// examples
ex := [0, 1, 2, 3]
- verifyEq(ex[0..2], [0, 1, 2])
- verifyEq(ex[3..3], [3])
- verifyEq(ex[-2..-1], [2, 3])
- verifyEq(ex[0..<2], [0, 1])
- verifyEq(ex[1..-2], [1, 2])
+ verifyGetRange(ex, 0..2, [0, 1, 2])
+ verifyGetRange(ex, 3..3, [3])
+ verifyGetRange(ex, -2..-1, [2, 3])
+ verifyGetRange(ex, 0..<2, [0, 1])
+ verifyGetRange(ex, 1..-2, [1, 2])
// errors
verifyErr(IndexErr#) { x:=list[0..4] }
@@ -578,6 +578,21 @@ class ListTest : Test
verifyErr(IndexErr#) { x:=list[1..5] }
}
+ Void verifyGetRange(Int[] list, Range r, Int[]? expected)
+ {
+ if (expected != null)
+ {
+echo("-- $list [$r] => " + list.getRange(r) + " ?= " + expected)
+ verifyEq(list[r], expected)
+ verifyEq(list.getRange(r), expected)
+ }
+ else
+ {
+ verifyErr(IndexErr#) { x := list[r] }
+ verifyErr(IndexErr#) { x := list.getRange(r) }
+ }
+ }
+
//////////////////////////////////////////////////////////////////////////
// Remove
//////////////////////////////////////////////////////////////////////////
@@ -1000,6 +1015,12 @@ class ListTest : Test
verifyEq([null, "a", 3, "b", null, 5ms].findType(Duration#), [5ms])
verifyEq(["a", 3, "b", 6sec, 5f].findType(Obj#), ["a", 3, "b", 6sec, 5f])
+ // findNonNull
+ verifyEq([1, null, 2].findNotNull, Int[1, 2])
+ verifyEq(Str?[null].findNotNull, Str[,])
+ verifyEq(Str?[null, "x", null, null, "y", null].findNotNull, Str["x", "y"])
+ verifyEq([null, 1, null, "foo"].findNotNull, Obj[1, "foo"])
+
// exclude
verifyEq(list.exclude|Int v, Int i->Bool| { return v % 20 == 0 }, [10, 30])
verifyEq(list.exclude|Int v, Int i->Bool| { return i % 2 == 0 }, [10, 30, 60])
@@ -1040,6 +1061,19 @@ class ListTest : Test
verifyEq(list.map |Int v, Int i->Bool| { return i%2==0 }, [true, false, true])
}
+//////////////////////////////////////////////////////////////////////////
+// MapNotNull
+//////////////////////////////////////////////////////////////////////////
+
+ Void testMapNotNull()
+ {
+ list := [3, 4, 5]
+ verifyEq(list.mapNotNull |Int v->Int?| { v.isOdd ? 10+v : null }, Int[13, 15])
+ verifyEq(list.mapNotNull |Int v->Int?| { null }, Int[,])
+ verifyEq(list.mapNotNull |Int v->Str?| { v.toStr }, Str["3", "4", "5"])
+ verifyEq(list.mapNotNull |Int v->Str| { v.toStr }, Str["3", "4", "5"])
+ }
+
//////////////////////////////////////////////////////////////////////////
// FlatMap
//////////////////////////////////////////////////////////////////////////
@@ -1053,6 +1087,28 @@ class ListTest : Test
verifyEq(list.flatMap |v, i->Int[]| { [v, i] }, ['a', 0, 'b', 1])
}
+//////////////////////////////////////////////////////////////////////////
+// GroupBy
+//////////////////////////////////////////////////////////////////////////
+
+ /* TODO add for 1.0.77
+ Void testGroupBy()
+ {
+ list := ["ape", "bear", "camel", "deer", "eel"]
+
+ verifyEq(list.groupBy { it.size }, Obj:Str[][3:["ape", "eel"], 4:["bear", "deer"], 5:["camel"]])
+ verifyEq(list.groupBy |s| { s.size }, Obj:Str[][3:["ape", "eel"], 4:["bear", "deer"], 5:["camel"]])
+ verifyEq(list.groupBy |s->Int| { s.size }, Int:Str[][3:["ape", "eel"], 4:["bear", "deer"], 5:["camel"]])
+ verifyEq(list.groupBy |Str s, Int i->Str| { i.toStr }, Str:Str[]["0":["ape"], "1":["bear"], "2":["camel"], "3":["deer"], "4":["eel"]])
+
+ map := Int:Str[][:]
+ list.groupByInto(map) { it.size }
+ verifyEq(map, Int:Str[][3:["ape", "eel"], 4:["bear", "deer"], 5:["camel"]])
+ ["fox", "goat"].groupByInto(map) |s| { s.size }
+ verifyEq(map, Int:Str[][3:["ape", "eel", "fox"], 4:["bear", "deer", "goat"], 5:["camel"]])
+ }
+ */
+
//////////////////////////////////////////////////////////////////////////
// Any/All
//////////////////////////////////////////////////////////////////////////
diff --git a/com.xored.f4.fantom/fantom/src/testSys/fan/MapTest.fan b/com.xored.f4.fantom/fantom/src/testSys/fan/MapTest.fan
index 5ec60d6c..87bc8bbe 100755
--- a/com.xored.f4.fantom/fantom/src/testSys/fan/MapTest.fan
+++ b/com.xored.f4.fantom/fantom/src/testSys/fan/MapTest.fan
@@ -485,17 +485,17 @@ class MapTest : Test
}
//////////////////////////////////////////////////////////////////////////
-// AddIfNotNull
+// AddNotNull
//////////////////////////////////////////////////////////////////////////
- Void testAddIfNotNull()
+ Void testAddNotNull()
{
m := Str:Str[:]
- verifySame(m.addIfNotNull("foo", null), m)
+ verifySame(m.addNotNull("foo", null), m)
verifyEq(m, Str:Str[:])
- verifySame(m.addIfNotNull("foo", "bar"), m)
+ verifySame(m.addNotNull("foo", "bar"), m)
verifyEq(m, Str:Str["foo":"bar"])
- verifySame(m.addIfNotNull("foo", null), m)
+ verifySame(m.addNotNull("foo", null), m)
verifyEq(m, Str:Str["foo":"bar"])
}
@@ -1044,6 +1044,11 @@ class MapTest : Test
verifyEq(mx2.caseInsensitive, true)
verifyEq(mx1["two"], 2)
verifyEq(mx2["two"], 2)
+
+
+ // findNull
+ mc = Str:Int?["x":1, "y":2, "z":null]
+ verifyEq(mc.findNotNull, Str:Int["x":1, "y":2])
}
//////////////////////////////////////////////////////////////////////////
@@ -1114,6 +1119,38 @@ class MapTest : Test
verifyEq(m["Foo"], "FOO")
}
+
+//////////////////////////////////////////////////////////////////////////
+// MapNotNull
+//////////////////////////////////////////////////////////////////////////
+
+ Void testMapNotNull()
+ {
+ m1 := Int:Int?[1:10, 2:null, 3:30, 4:null]
+ verifyEq(m1.mapNotNull |v->Str?| { v?.toStr }, Int:Str[1:"10", 3:"30"])
+
+ // ordered
+ m2 := Int:Int[:]
+ m2.ordered = true
+ m2[1] = 'a'
+ m2[2] = 'b'
+ m2[3] = 'c'
+ m2x := m2.mapNotNull |v->Str?| { v == 'b' ? null : v.toChar.upper }
+ verifyEq(m2x.ordered, true)
+ verifyEq(m2x, Int:Str[1:"A", 3:"C"])
+
+ // case insensitive
+ m3 := Str:Int[:]
+ m3.caseInsensitive = true
+ m3["a"] = 100
+ m3["b"] = 200
+ m3["c"] = 300
+ m3x := m3.mapNotNull |v, k->Int?| { k == "b" ? null : v / 100 }
+ verifyEq(m3x.caseInsensitive, true)
+ verifyEq(m3x, ["a":1, "c":3])
+ verifyEq(m3x["C"], 3)
+ }
+
//////////////////////////////////////////////////////////////////////////
// AssignOps
//////////////////////////////////////////////////////////////////////////
diff --git a/com.xored.f4.fantom/fantom/src/testSys/fan/PodTest.fan b/com.xored.f4.fantom/fantom/src/testSys/fan/PodTest.fan
index 10805d71..ee9422d8 100755
--- a/com.xored.f4.fantom/fantom/src/testSys/fan/PodTest.fan
+++ b/com.xored.f4.fantom/fantom/src/testSys/fan/PodTest.fan
@@ -127,6 +127,8 @@ class PodTest : Test
verifyEq(f.name, "test.txt")
verifyEq(f.size, 19)
verifyEq(f.readAllStr, "hello world\nline 2")
+ verify(f.isReadable)
+ verifyFalse(f.isWritable)
}
//////////////////////////////////////////////////////////////////////////
@@ -155,6 +157,64 @@ class PodTest : Test
verifySame(pod.props(`not/found`, 1ms), pod.props(`not/found`, 1ms))
}
+
+//////////////////////////////////////////////////////////////////////////
+// Flatten Depends
+//////////////////////////////////////////////////////////////////////////
+
+ Void testFlattenDepends()
+ {
+ verifyFlattenDepends(
+ ["fluxText"],
+ ["sys", "concurrent", "compiler", "gfx", "fwt", "flux", "syntax", "fluxText"])
+
+ verifyFlattenDepends(
+ ["fluxText", "sys", "fwt"],
+ ["sys", "concurrent", "compiler", "gfx", "fwt", "flux", "syntax", "fluxText"])
+
+ verifyFlattenDepends(
+ ["fluxText", "webmod"],
+ ["sys", "concurrent", "compiler", "gfx", "fwt", "flux", "syntax", "fluxText", "util", "inet", "web", "webmod"])
+ }
+
+ Void verifyFlattenDepends(Str[] names, Str[] expected)
+ {
+ pods := (Pod[])names.map |n->Pod| { Pod.find(n) }
+ pods = Pod.flattenDepends(pods)
+ actual := pods.map |p->Str | { p.name }
+ verifyEq(expected.sort, actual.sort)
+ }
+
+//////////////////////////////////////////////////////////////////////////
+// Order By Depends
+//////////////////////////////////////////////////////////////////////////
+
+ Void testOrderByDepends()
+ {
+ verifyOrderByDepends(
+ ["sys"],
+ ["sys"])
+
+ verifyOrderByDepends(
+ ["concurrent", "sys"],
+ ["sys", "concurrent"])
+
+ verifyOrderByDepends(
+ ["web", "inet", "concurrent", "sys"],
+ ["sys", "concurrent", "inet", "web"])
+
+ big := ["sys", "concurrent", "gfx", "fwt", "flux", "syntax", "fluxText"]
+ 10.times { verifyOrderByDepends(big.dup.shuffle, big) }
+ }
+
+ Void verifyOrderByDepends(Str[] names, Str[] expected)
+ {
+ pods := (Pod[])names.map |n->Pod| { Pod.find(n) }
+ pods = Pod.orderByDepends(pods)
+ actual := pods.map |p->Str | { p.name }
+ verifyEq(expected, actual)
+ }
+
//////////////////////////////////////////////////////////////////////////
// Reload
//////////////////////////////////////////////////////////////////////////
diff --git a/com.xored.f4.fantom/fantom/src/testSys/fan/StrTest.fan b/com.xored.f4.fantom/fantom/src/testSys/fan/StrTest.fan
index c612b17a..46923764 100755
--- a/com.xored.f4.fantom/fantom/src/testSys/fan/StrTest.fan
+++ b/com.xored.f4.fantom/fantom/src/testSys/fan/StrTest.fan
@@ -310,10 +310,10 @@ class StrTest : Test
}
//////////////////////////////////////////////////////////////////////////
-// Slice
+// Get Range
//////////////////////////////////////////////////////////////////////////
- Void testSlice()
+ Void testGetRange()
{
/* Ruby
irb(main):001:0> "abcd"[0..1] => "ab"
@@ -349,48 +349,63 @@ class StrTest : Test
// TODO: not clear how error handling should work...
s := "abcd"
- verifyEq(s[0..1], "ab")
- verifyEq(s[0..<0], "")
- verifyEq(s[0..2], "abc")
- verifyEq(s[0..3], "abcd")
- verifyEq(s[1..1], "b")
- verifyEq(s[1..2], "bc")
- verifyEq(s[1..3], "bcd")
- verifyEq(s[3..2], "")
- verifyEq(s[3..3], "d")
- verifyEq(s[4..-1], "")
- verifyEq(s[0..<1], "a")
- verifyEq(s[0..<2], "ab")
- verifyEq(s[0..<3], "abc")
- verifyEq(s[0..<4], "abcd")
- verifyEq(s[0..-1], "abcd")
- verifyEq(s[0..-2], "abc")
- verifyEq(s[0..-3], "ab")
- verifyEq(s[0..-4], "a")
- verifyEq(s[0..-5], "")
- verifyEq(s[0..<-1], "abc")
- verifyEq(s[0..<-2], "ab")
- verifyEq(s[0..<-3], "a")
- verifyEq(s[1..<-3], "")
- verifyEq(s[1..<-1], "bc")
- verifyEq(s[-3..<-1], "bc")
- verifyEq(s[-2..<-1], "c")
- verifyEq(s[-3..<-1], "bc")
- verifyEq(s[-1..<-1], "")
+ verifyGetRange(s, 0..1, "ab")
+ verifyGetRange(s, 0..<0, "")
+ verifyGetRange(s, 0..2, "abc")
+ verifyGetRange(s, 0..3, "abcd")
+ verifyGetRange(s, 1..1, "b")
+ verifyGetRange(s, 1..2, "bc")
+ verifyGetRange(s, 1..3, "bcd")
+ verifyGetRange(s, 3..2, "")
+ verifyGetRange(s, 3..3, "d")
+ verifyGetRange(s, 4..-1, "")
+ verifyGetRange(s, 0..<1, "a")
+ verifyGetRange(s, 0..<2, "ab")
+ verifyGetRange(s, 0..<3, "abc")
+ verifyGetRange(s, 0..<4, "abcd")
+ verifyGetRange(s, 0..-1, "abcd")
+ verifyGetRange(s, 0..-2, "abc")
+ verifyGetRange(s, 0..-3, "ab")
+ verifyGetRange(s, 0..-4, "a")
+ verifyGetRange(s, 0..-5, "")
+ verifyGetRange(s, 0..<-1, "abc")
+ verifyGetRange(s, 0..<-2, "ab")
+ verifyGetRange(s, 0..<-3, "a")
+ verifyGetRange(s, 1..<-3, "")
+ verifyGetRange(s, 1..<-1, "bc")
+ verifyGetRange(s, -3..<-1, "bc")
+ verifyGetRange(s, -2..<-1, "c")
+ verifyGetRange(s, -3..<-1, "bc")
+ verifyGetRange(s, -1..<-1, "")
// examples
- verifyEq("abcd"[0..2], "abc")
- verifyEq("abcd"[3..3], "d")
- verifyEq("abcd"[-2..-1], "cd")
- verifyEq("abcd"[0..<2], "ab")
- verifyEq("abcd"[1..-2], "bc")
-
-
- verifyErr(IndexErr#) { x:=s[0..4] }
- verifyErr(IndexErr#) { x:=s[1..4] }
- verifyErr(IndexErr#) { x:=s[3..1] }
- verifyErr(IndexErr#) { x:=s[3..<2] }
- verifyErr(IndexErr#) { x:=s[0..<5] }
+ verifyGetRange("abcd", 0..2, "abc")
+ verifyGetRange("abcd", 3..3, "d")
+ verifyGetRange("abcd", -2..-1, "cd")
+ verifyGetRange("abcd", 0..<2, "ab")
+ verifyGetRange("abcd", 1..-2, "bc")
+
+
+ verifyGetRange(s, 0..4, null)
+ verifyGetRange(s, 1..4, null)
+ verifyGetRange(s, 3..1, null)
+ verifyGetRange(s, 3..<2, null)
+ verifyGetRange(s, 0..<5, null)
+ }
+
+ Void verifyGetRange(Str s, Range r, Str? expected)
+ {
+ if (expected != null)
+ {
+echo("-- $s[$r] => " + s.getRange(r) + " ?= " + expected)
+ verifyEq(s[r], expected)
+ verifyEq(s.getRange(r), expected)
+ }
+ else
+ {
+ verifyErr(IndexErr#) { x := s[r] }
+ verifyErr(IndexErr#) { x := s.getRange(r) }
+ }
}
//////////////////////////////////////////////////////////////////////////
diff --git a/com.xored.f4.fantom/fantom/src/util/build.fan b/com.xored.f4.fantom/fantom/src/util/build.fan
index b53c8373..eeb969d9 100755
--- a/com.xored.f4.fantom/fantom/src/util/build.fan
+++ b/com.xored.f4.fantom/fantom/src/util/build.fan
@@ -20,12 +20,12 @@ class Build : BuildPod
podName = "util"
summary = "Utilities"
meta = ["org.name": "Fantom",
- "org.uri": "http://fantom.org/",
+ "org.uri": "https://fantom.org/",
"proj.name": "Fantom Core",
- "proj.uri": "http://fantom.org/",
+ "proj.uri": "https://fantom.org/",
"license.name": "Academic Free License 3.0",
- "vcs.name": "Mercurial",
- "vcs.uri": "https://bitbucket.org/fantom/fan-1.0/"]
+ "vcs.name": "Git",
+ "vcs.uri": "https://github.com/fantom-lang/fantom"]
depends = ["sys 1.0", "concurrent 1.0"]
srcDirs = [`fan/`, `test/`]
javaDirs = [`java/`]
diff --git a/com.xored.f4.fantom/fantom/src/util/fan/BoolArray.fan b/com.xored.f4.fantom/fantom/src/util/fan/BoolArray.fan
index e24b8ab8..08f8f227 100755
--- a/com.xored.f4.fantom/fantom/src/util/fan/BoolArray.fan
+++ b/com.xored.f4.fantom/fantom/src/util/fan/BoolArray.fan
@@ -38,11 +38,20 @@ native final class BoolArray
** Negative indices are *not* supported.
@Operator Void set(Int index, Bool val)
+ ** Set the value at given index and return the previous value.
+ Bool getAndSet(Int index, Bool val)
+
** Fill this array with the given boolean value. If range is null
** then the entire array is filled, otherwise just the specified range.
** Return this.
This fill(Bool val, Range? range := null)
+ ** Set entire array to false
+ This clear()
+
+ ** Iterate each index set to true
+ Void eachTrue(|Int index| f)
+
** Copy the booleans from 'that' array into this array and return this.
This copyFrom(BoolArray that)
diff --git a/com.xored.f4.fantom/fantom/src/util/java/BoolArray.java b/com.xored.f4.fantom/fantom/src/util/java/BoolArray.java
index aa6af7b5..28844a0e 100755
--- a/com.xored.f4.fantom/fantom/src/util/java/BoolArray.java
+++ b/com.xored.f4.fantom/fantom/src/util/java/BoolArray.java
@@ -41,9 +41,22 @@ public final void set(long index, boolean v)
words[i>>0x5] &= ~mask;
}
+ public final boolean getAndSet(long index, boolean v)
+ {
+ int i = (int)index;
+ int mask = 1 << (i & 0x1F);
+ boolean prev = (words[i>>0x5] & mask) != 0;
+ if (v)
+ words[i>>0x5] |= mask;
+ else
+ words[i>>0x5] &= ~mask;
+ return prev;
+ }
+
public BoolArray fill(boolean val) { return fill(val, null); }
public BoolArray fill(boolean val, Range range)
{
+ if (range == null && !val) return clear();
int start, end;
int size = (int)size();
if (range == null) { start = 0; end = size-1; }
@@ -52,6 +65,25 @@ public BoolArray fill(boolean val, Range range)
return this;
}
+ public BoolArray clear()
+ {
+ for (int i=0; i 0) lastIsNewline = buf[-1] == '\n'
+ out.writeBuf(buf.flip, buf.remaining)
+ }
+ if (!lastIsNewline) out.writeChar('\n')
+ }
+ finally { in.close }
+ }
+
+//////////////////////////////////////////////////////////////////////////
+// JavaScript Utils
+//////////////////////////////////////////////////////////////////////////
+
+ ** Given a set of pods return a list of JavaScript files that
+ ** form a complete Fantom application:
+ ** - flatten the pods using `sys::Pod.flattenDepends`
+ ** - order them by dependencies using `sys::Pod.orderByDepends`
+ ** - insert `toEtcJsFiles` immediately after "sys.js"
+ static File[] toAppJsFiles(Pod[] pods)
+ {
+ pods = Pod.flattenDepends(pods)
+ pods = Pod.orderByDepends(pods)
+ files := toPodJsFiles(pods)
+ files.insertAll(1, toEtcJsFiles)
+ return files
+ }
+
+ ** Get the standard pod JavaScript file or null if no JS code. The
+ ** standard location used by the Fantom JS compiler is "/{pod-name}.js"
+ static File? toPodJsFile(Pod pod)
+ {
+ pod.file(`/${pod.name}.js`, false)
+ }
+
+ ** Map a set of pods to "/{name}.js" JavaScript files.
+ ** Ignore pods that are missing a JavaScript file.
+ ** This method does *not* flatten/order the pods.
+ static File[] toPodJsFiles(Pod[] pods)
+ {
+ acc := File[,]
+ acc.capacity = pods.size
+ pods.each |pod|
+ {
+ js := toPodJsFile(pod)
+ if (js != null) acc.add(js)
+ }
+ return acc
+ }
+
+ ** Return the required sys etc files:
+ ** - add `toMimeJsFile`
+ ** - add `toUnitsJsFile`
+ ** - add `toTimezonesJsFile`
+ ** - add `toIndexPropsJsFile`
+ static File[] toEtcJsFiles()
+ {
+ [toMimeJsFile, toUnitsJsFile, toTimezonesJsFile, toIndexPropsJsFile]
+ }
+
+ ** Compile the mime type database into a Javascript file "mime.js"
+ static File toMimeJsFile()
+ {
+ buf := Buf(4096)
+ c := Type.find("compilerJs::JsExtToMime").make
+ c->write(buf.out)
+ return buf.toFile(`mime.js`)
+ }
+
+ ** Compile the unit database into a JavaScript file "unit.js"
+ static File toUnitsJsFile()
+ {
+ buf := Buf(50_000)
+ c := Type.find("compilerJs::JsUnitDatabase").make
+ c->write(buf.out)
+ return buf.toFile(`units.js`)
+ }
+
+ ** Compile the timezone database into a JavaScript file "tz.js"
+ static File toTimezonesJsFile()
+ {
+ Env.cur.homeDir + `etc/sys/tz.js`
+ }
+
+ ** Compile the indexed props database into a JavaScript file "index-props.js"
+ static File toIndexPropsJsFile(Pod[] pods := Pod.list)
+ {
+ buf := Buf(10_000)
+ c := Type.find("compilerJs::JsIndexedProps").make
+ c->write(buf.out, pods)
+ return buf.toFile(`index-props.js`)
+ }
+
+ ** Compile the locale props into a JavaScript file "{locale}.js"
+ static File toLocaleJsFile(Locale locale, Pod[] pods := Pod.list)
+ {
+ buf := Buf(1024)
+ m := Slot.findMethod("compilerJs::JsProps.writeProps")
+ path := `locale/${locale.toStr}.props`
+ pods.each |pod| { m.call(buf.out, pod, path, 1sec) }
+ return buf.toFile(`${locale}.js`)
+ }
+
+ ** Compile a list of pod JavaScript files into a single unified source
+ ** map file. The list of files passed to this method should match
+ ** exactly the list of files used to create the corresponding JavaScript
+ ** FilePack. If the file is the standard pod JS file, then we will include
+ ** an offset version of "{pod}.js.map" generated by the JavaScript compiler.
+ ** Otherwise if the file is another JavaScript file (such as units.js) then
+ ** we just add the appropiate offset.
+ **
+ ** The 'sourceRoot' option may be passed in to replace "/dev/{podName}"
+ ** as the root URI used to fetch source files from the server.
+ static File toPodJsMapFile(File[] files, [Str:Obj]? options := null)
+ {
+ buf := Buf(4 * 1024 * 1024)
+ m := Slot.findMethod("compilerJs::SourceMap.pack")
+ m.call(files, buf.out, options)
+ return buf.toFile(`js.map`)
+ }
+
+//////////////////////////////////////////////////////////////////////////
+// CSS Utils
+//////////////////////////////////////////////////////////////////////////
+
+ ** Given a set of pods return a list of CSS files that
+ ** form a complete Fantom application:
+ ** - flatten the pods using `sys::Pod.flattenDepends`
+ ** - order them by dependencies using `sys::Pod.orderByDepends`
+ ** - return `toPodCssFiles`
+ static File[] toAppCssFiles(Pod[] pods)
+ {
+ pods = Pod.flattenDepends(pods)
+ pods = Pod.orderByDepends(pods)
+ return toPodCssFiles(pods)
+ }
+
+ ** Map a set of pods to "/res/css/{name}.css" CSS files.
+ ** Ignore pods that are missing a CSS file.
+ ** This method does *not* flatten/order the pods.
+ static File[] toPodCssFiles(Pod[] pods)
+ {
+ acc := File[,]
+ pods.each |pod|
+ {
+ css := pod.file(`/res/css/${pod.name}.css`, false)
+ if (css != null) acc.add(css)
+ }
+ return acc
+ }
+
+//////////////////////////////////////////////////////////////////////////
+// Main
+//////////////////////////////////////////////////////////////////////////
+
+ ** Test program
+ @NoDoc static Void main(Str[] args)
+ {
+ pods := args.map |n->Pod| { Pod.find(n) }
+ mainReport(toAppJsFiles(pods))
+ mainReport(toAppCssFiles(pods))
+ }
+
+ private static Void mainReport(File[] f)
+ {
+ b := makeFiles(f)
+ gzip := b.buf.size.toLocale("B")
+ echo("$f.first.ext: $f.size files, $gzip, $b.mimeType")
+ }
+
+}
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/web/fan/FileWeblet.fan b/com.xored.f4.fantom/fantom/src/web/fan/FileWeblet.fan
index de2228de..e74a78a3 100755
--- a/com.xored.f4.fantom/fantom/src/web/fan/FileWeblet.fan
+++ b/com.xored.f4.fantom/fantom/src/web/fan/FileWeblet.fan
@@ -148,6 +148,10 @@ class FileWeblet : Weblet
{
if (mime.subType == "json") return true
}
+ if (mime.mediaType == "image")
+ {
+ if (mime.subType == "svg+xml") return true
+ }
return false
}
@@ -159,12 +163,19 @@ class FileWeblet : Weblet
** "If-Modified-Since" modification time.
**
virtual protected Bool checkNotModified()
+ {
+ doCheckNotModified(req, res, etag, modified)
+ }
+
+ **
+ ** Utility for standard check modified logic
+ **
+ internal static Bool doCheckNotModified(WebReq req, WebRes res, Str etag, DateTime modified)
{
// check If-Match-None
matchNone := req.headers["If-None-Match"]
if (matchNone != null)
{
- etag := this.etag
match := WebUtil.parseList(matchNone).any |Str s->Bool|
{
return s == etag || s == "*"
diff --git a/com.xored.f4.fantom/fantom/src/web/fan/WebClient.fan b/com.xored.f4.fantom/fantom/src/web/fan/WebClient.fan
index cd64ea19..f4d6cc71 100755
--- a/com.xored.f4.fantom/fantom/src/web/fan/WebClient.fan
+++ b/com.xored.f4.fantom/fantom/src/web/fan/WebClient.fan
@@ -260,6 +260,21 @@ class WebClient
return Regex[,]
}
+//////////////////////////////////////////////////////////////////////////
+// Authentication
+//////////////////////////////////////////////////////////////////////////
+
+ **
+ ** Authenticate request using HTTP Basic with given username
+ ** and password.
+ **
+ This authBasic(Str username, Str password)
+ {
+ enc := "${username}:${password}".toBuf.toBase64
+ reqHeaders["Authorization"] = "Basic ${enc}"
+ return this
+ }
+
//////////////////////////////////////////////////////////////////////////
// Get
//////////////////////////////////////////////////////////////////////////
@@ -305,63 +320,85 @@ class WebClient
}
//////////////////////////////////////////////////////////////////////////
-// Post
+// Post/Patch
//////////////////////////////////////////////////////////////////////////
**
- ** Make a post request to the URI with the given form data.
- ** Set the Content-Type to application/x-www-form-urlencoded.
- ** Upon completion the response is ready to be read. This method
- ** does not support the ["Expect" header]`pod-doc#expectContinue` (it
- ** posts all form data before reading response).
+ ** Convenience for 'writeForm("POST", form).readRes'
**
This postForm(Str:Str form)
+ {
+ writeForm("POST", form).readRes
+ }
+
+ **
+ ** Convenience for 'writeStr("POST", content).readRes'
+ **
+ This postStr(Str content)
+ {
+ writeStr("POST", content).readRes
+ }
+
+ **
+ ** Convenience for 'writeFile("POST", file).readRes'
+ **
+ This postFile(File file)
+ {
+ writeFile("POST", file).readRes
+ }
+
+ **
+ ** Make a request with the given HTTP method to the URI with the given form data.
+ ** Set the Content-Type to application/x-www-form-urlencoded.
+ ** This method does not support the ["Expect" header]`pod-doc#expectContinue` (it
+ ** writes all form data before reading response). Should primarily be used for POST
+ ** and PATCH requests.
+ **
+ This writeForm(Str method, Str:Str form)
{
if (reqHeaders["Expect"] != null) throw UnsupportedErr("'Expect' header")
body := Uri.encodeQuery(form)
- reqMethod = "POST"
+ reqMethod = method
reqHeaders["Content-Type"] = "application/x-www-form-urlencoded"
reqHeaders["Content-Length"] = body.size.toStr // encoded form is ASCII
writeReq
reqOut.print(body).close
- readRes
return this
}
**
- ** Make a post request to the URI using UTF-8 encoding of given
+ ** Make a request with the given HTTP method to the URI using UTF-8 encoding of given
** string. If Content-Type is not already set, then set it
- ** to "text/plain; charset=utf-8". Upon completion the response
- ** is ready to be read. This method does not support the
- ** ["Expect" header]`pod-doc#expectContinue` (it posts full string
- ** before reading response).
+ ** to "text/plain; charset=utf-8". This method does not support the
+ ** ["Expect" header]`pod-doc#expectContinue` (it writes full string
+ ** before reading response). Should primarily be used for "POST" and "PATCH"
+ ** requests.
**
- This postStr(Str content)
+ This writeStr(Str method, Str content)
{
if (reqHeaders["Expect"] != null) throw UnsupportedErr("'Expect' header")
body := Buf().print(content).flip
- reqMethod = "POST"
+ reqMethod = method
ct := reqHeaders["Content-Type"]
if (ct == null)
reqHeaders["Content-Type"] = "text/plain; charset=utf-8"
reqHeaders["Content-Length"] = body.size.toStr
writeReq
reqOut.writeBuf(body).close
- readRes
return this
}
**
- ** Post a file to the URI. If Content-Type header is not already
- ** set, then it is set from the file extension's MIME type. Upon
- ** completion the response is ready to be read. This method does
+ ** Write a file using the given HTTP method to the URI. If Content-Type header is not already
+ ** set, then it is set from the file extension's MIME type. This method does
** not support the ["Expect" header]`pod-doc#expectContinue` (it
- ** posts full file before reading response).
+ ** writes full file before reading response). Should primarily be used for "POST" and
+ ** "PATCH" requests.
**
- This postFile(File file)
+ This writeFile(Str method, File file)
{
if (reqHeaders["Expect"] != null) throw UnsupportedErr("'Expect' header")
- reqMethod = "POST"
+ reqMethod = method
ct := reqHeaders["Content-Type"]
if (ct == null)
reqHeaders["Content-Type"] = file.mimeType?.toStr ?: "application/octet-stream"
@@ -370,7 +407,6 @@ class WebClient
writeReq
file.in.pipe(reqOut, file.size)
reqOut.close
- readRes
return this
}
@@ -443,6 +479,7 @@ class WebClient
socket.connect(IpAddr(proxy.host), proxy.port ?: 80)
out := socket.out
out.print("CONNECT ${reqUri.host}:${reqUri.port ?: 443} HTTP/${reqVersion}").print("\r\n")
+ .print("Host: ${reqUri.host}:${reqUri.port ?: 443}").print("\r\n")
.print("\r\n")
out.flush
@@ -471,7 +508,7 @@ class WebClient
try
{
// parse status-line
- res = in.readLine ?: throw IOErr("No response")
+ res = WebUtil.readLine(in)
if (res.startsWith("HTTP/1.1")) resVersion = ver11
else if (res.startsWith("HTTP/1.0")) resVersion = ver10
else throw Err("Not HTTP")
diff --git a/com.xored.f4.fantom/fantom/src/web/fan/WebSocket.fan b/com.xored.f4.fantom/fantom/src/web/fan/WebSocket.fan
index c7fa2a76..d2f6510e 100644
--- a/com.xored.f4.fantom/fantom/src/web/fan/WebSocket.fan
+++ b/com.xored.f4.fantom/fantom/src/web/fan/WebSocket.fan
@@ -36,6 +36,7 @@ class WebSocket
c.reqHeaders["Upgrade"] = "websocket"
c.reqHeaders["Connection"] = "Upgrade"
c.reqHeaders["Sec-WebSocket-Key"] = key
+ c.reqHeaders["Sec-WebSocket-Version"] = "13"
if (headers != null) c.reqHeaders.addAll(headers)
c.writeReq
diff --git a/com.xored.f4.fantom/fantom/src/web/fan/WebUtil.fan b/com.xored.f4.fantom/fantom/src/web/fan/WebUtil.fan
index 9ef52783..07d89c16 100755
--- a/com.xored.f4.fantom/fantom/src/web/fan/WebUtil.fan
+++ b/com.xored.f4.fantom/fantom/src/web/fan/WebUtil.fan
@@ -128,7 +128,7 @@ class WebUtil
// continuation of last header field
if (peek.isSpace && last != null)
{
- headers[last] += " " + in.readLine.trim
+ headers[last] += " " + WebUtil.readLine(in).trim
continue
}
@@ -371,6 +371,19 @@ class WebUtil
return ChunkOutStream(out)
}
+ **
+ ** Read line of HTTP protocol. Raise exception if unexpected
+ ** end of stream or the line exceeds our max size.
+ **
+ @NoDoc static Str readLine(InStream in)
+ {
+ max := 65536 // 64KB
+ line := in.readLine(max)
+ if (line == null) throw IOErr("Unexpected end of stream")
+ if (line.size == max) throw IOErr("Max request line")
+ return line
+ }
+
//////////////////////////////////////////////////////////////////////////
// Multi-Part Forms
//////////////////////////////////////////////////////////////////////////
@@ -385,7 +398,7 @@ class WebUtil
static Void parseMultiPart(InStream in, Str boundary, |Str:Str headers, InStream in| cb)
{
boundary = "--" + boundary
- line := in.readLine
+ line := WebUtil.readLine(in)
if (line == boundary + "--") return
if (line != boundary) throw IOErr("Expecting boundry line $boundary.toCode")
while (true)
@@ -523,10 +536,10 @@ internal class ChunkInStream : InStream
if (noMoreChunks) return false
// we expect \r\n unless this is first chunk
- if (chunkRem != -1 && !in.readLine.isEmpty) throw Err()
+ if (chunkRem != -1 && !WebUtil.readLine(in).isEmpty) throw Err()
// read the next chunk status line
- line := in.readLine
+ line := WebUtil.readLine(in)
semi := line.index(";")
if (semi != null) line = line[0..semi]
chunkRem = line.trim.toInt(16)
diff --git a/com.xored.f4.fantom/fantom/src/web/test/FilePackTest.fan b/com.xored.f4.fantom/fantom/src/web/test/FilePackTest.fan
new file mode 100644
index 00000000..4c780b22
--- /dev/null
+++ b/com.xored.f4.fantom/fantom/src/web/test/FilePackTest.fan
@@ -0,0 +1,30 @@
+//
+// Copyright (c) 2020, Brian Frank and Andy Frank
+// Licensed under the Academic Free License version 3.0
+//
+// History:
+// 11 May 2020 Brian Frank Creation
+//
+
+using concurrent
+
+**
+** FilePackTest
+**
+class FilePackTest : Test
+{
+
+ Void testPack()
+ {
+ buf := Buf()
+ FilePack.pack([
+ "a\n".toBuf.toFile(`a.txt`),
+ "b".toBuf.toFile(`b.txt`),
+ "c\n".toBuf.toFile(`c.txt`),
+ "".toBuf.toFile(`d.txt`),
+ "e".toBuf.toFile(`e.txt`),
+ ], buf.out)
+ buf = buf.toImmutable
+ verifyEq(buf.in.readAllStr, "a\nb\nc\ne\n")
+ }
+}
\ No newline at end of file
diff --git a/com.xored.f4.fantom/fantom/src/webfwt/build.fan b/com.xored.f4.fantom/fantom/src/webfwt/build.fan
index cbe8cdb4..b689e4ce 100644
--- a/com.xored.f4.fantom/fantom/src/webfwt/build.fan
+++ b/com.xored.f4.fantom/fantom/src/webfwt/build.fan
@@ -21,11 +21,11 @@ class Build : BuildPod
podName = "webfwt"
summary = "Web extensions to the FWT toolkit"
meta = ["org.name": "Fantom",
- "org.uri": "http://fantom.org/",
+ "org.uri": "https://fantom.org/",
"proj.name": "Fantom Core",
"license.name": "Academic Free License 3.0",
- "vcs.name": "Mercurial",
- "vcs.uri": "https://bitbucket.org/fantom/fan-1.0/"]
+ "vcs.name": "Git",
+ "vcs.uri": "https://github.com/fantom-lang/fantom"]
depends = ["sys 1.0", "gfx 1.0", "fwt 1.0", "web 1.0"]
srcDirs = [`fan/`,
//`fan/internal/`,
diff --git a/com.xored.f4.fantom/fantom/src/webmod/build.fan b/com.xored.f4.fantom/fantom/src/webmod/build.fan
index 78e5b7fd..5c5ee2b3 100755
--- a/com.xored.f4.fantom/fantom/src/webmod/build.fan
+++ b/com.xored.f4.fantom/fantom/src/webmod/build.fan
@@ -19,12 +19,12 @@ class Build : BuildPod
podName = "webmod"
summary = "Standard library of WebMods"
meta = ["org.name": "Fantom",
- "org.uri": "http://fantom.org/",
+ "org.uri": "https://fantom.org/",
"proj.name": "Fantom Core",
- "proj.uri": "http://fantom.org/",
+ "proj.uri": "https://fantom.org/",
"license.name": "Academic Free License 3.0",
- "vcs.name": "Mercurial",
- "vcs.uri": "https://bitbucket.org/fantom/fan-1.0/"]
+ "vcs.name": "Git",
+ "vcs.uri": "https://github.com/fantom-lang/fantom"]
depends = ["sys 1.0", "inet 1.0", "web 1.0", "util 1.0"]
srcDirs = [`fan/`]
docSrc = true
diff --git a/com.xored.f4.fantom/fantom/src/wisp/build.fan b/com.xored.f4.fantom/fantom/src/wisp/build.fan
index 8c6fd840..d666631b 100755
--- a/com.xored.f4.fantom/fantom/src/wisp/build.fan
+++ b/com.xored.f4.fantom/fantom/src/wisp/build.fan
@@ -19,12 +19,12 @@ class Build : BuildPod
podName = "wisp"
summary = "Wisp web Server"
meta = ["org.name": "Fantom",
- "org.uri": "http://fantom.org/",
+ "org.uri": "httsp://fantom.org/",
"proj.name": "Fantom Core",
- "proj.uri": "http://fantom.org/",
+ "proj.uri": "https://fantom.org/",
"license.name": "Academic Free License 3.0",
- "vcs.name": "Mercurial",
- "vcs.uri": "https://bitbucket.org/fantom/fan-1.0/"]
+ "vcs.name": "Git",
+ "vcs.uri": "https://github.com/fantom-lang/fantom"]
depends = ["sys 1.0", "util 1.0", "concurrent 1.0", "inet 1.0", "web 1.0"]
srcDirs = [`fan/`, `test/`]
docSrc = true
diff --git a/com.xored.f4.fantom/fantom/src/wisp/fan/WispActor.fan b/com.xored.f4.fantom/fantom/src/wisp/fan/WispActor.fan
index fb9c2113..30a0fdc0 100755
--- a/com.xored.f4.fantom/fantom/src/wisp/fan/WispActor.fan
+++ b/com.xored.f4.fantom/fantom/src/wisp/fan/WispActor.fan
@@ -112,13 +112,8 @@ internal const class WispActor : Actor
{
// skip leading CRLF (4.1)
in := req.socket.in
- line := in.readLine
- if (line == null) throw Err("Empty request line")
- while (line.isEmpty)
- {
- line = in.readLine
- if (line == null) throw Err("Empty request line")
- }
+ line := WebUtil.readLine(in)
+ while (line.isEmpty) line = WebUtil.readLine(in)
// parse request-line (5.1)
toks := line.split
diff --git a/com.xored.f4.fantom/fantom/src/wisp/fan/WispService.fan b/com.xored.f4.fantom/fantom/src/wisp/fan/WispService.fan
index ede77d89..f1e62676 100755
--- a/com.xored.f4.fantom/fantom/src/wisp/fan/WispService.fan
+++ b/com.xored.f4.fantom/fantom/src/wisp/fan/WispService.fan
@@ -302,7 +302,7 @@ internal const class WispDefaultRootMod : WebMod
.h1.w("Wisp").h1End
.p.w("Wisp is running!").pEnd
.p.w("Currently there is no WebMod installed on this server.").pEnd
- .p.w("See wisp::pod-doc
+ .p.w("See wisp::pod-doc
to configure a WebMod for the server.").pEnd
.bodyEnd
.htmlEnd
diff --git a/com.xored.f4.fantom/fantom/src/xml/build.fan b/com.xored.f4.fantom/fantom/src/xml/build.fan
index 2959f862..128b1803 100755
--- a/com.xored.f4.fantom/fantom/src/xml/build.fan
+++ b/com.xored.f4.fantom/fantom/src/xml/build.fan
@@ -19,12 +19,12 @@ class Build : BuildPod
podName = "xml"
summary = "XML Parser and Document Modeling"
meta = ["org.name": "Fantom",
- "org.uri": "http://fantom.org/",
+ "org.uri": "https://fantom.org/",
"proj.name": "Fantom Core",
- "proj.uri": "http://fantom.org/",
+ "proj.uri": "https://fantom.org/",
"license.name": "Academic Free License 3.0",
- "vcs.name": "Mercurial",
- "vcs.uri": "https://bitbucket.org/fantom/fan-1.0/"]
+ "vcs.name": "Git",
+ "vcs.uri": "https://github.com/fantom-lang/fantom"]
depends = ["sys 1.0"]
srcDirs = [`fan/`, `test/`]
docSrc = true
diff --git a/com.xored.f4.fantom/plugin.xml b/com.xored.f4.fantom/plugin.xml
index f1539e64..6d1b01ac 100644
--- a/com.xored.f4.fantom/plugin.xml
+++ b/com.xored.f4.fantom/plugin.xml
@@ -8,7 +8,7 @@
home="fantom/bin/fant"
id="com.xored.f4.fantom.bundled"
interpreterInstallType="com.xored.fanide.internal.debug.ui.launcher.GenericFanInstallType"
- name="fantom-1.0.74-embedded">
+ name="fantom-1.0.76-embedded">
diff --git a/com.xored.f4.fantom/pom.xml b/com.xored.f4.fantom/pom.xml
index 54a317ad..ad0b336e 100644
--- a/com.xored.f4.fantom/pom.xml
+++ b/com.xored.f4.fantom/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.f4.fantom
- 1.0.74-SNAPSHOT
+ 1.0.76-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.f4.fcode.ui/META-INF/MANIFEST.MF b/com.xored.f4.fcode.ui/META-INF/MANIFEST.MF
index 4631b772..297119f9 100644
--- a/com.xored.f4.fcode.ui/META-INF/MANIFEST.MF
+++ b/com.xored.f4.fcode.ui/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: F4 Fcode UI
Bundle-SymbolicName: com.xored.f4.fcode.ui;singleton:=true
-Bundle-Version: 1.1.4.qualifier
+Bundle-Version: 1.1.6.qualifier
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.core.resources,
org.fantom.sys,
@@ -10,11 +10,11 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.ui,
org.eclipse.dltk.ui,
org.eclipse.ui.ide,
- com.xored.fanide.core;bundle-version="1.1.4",
+ com.xored.fanide.core;bundle-version="1.1.6",
org.eclipse.dltk.core,
org.eclipse.jface.text,
- com.xored.fanide.ui;bundle-version="1.1.4",
- com.xored.f4.fcode;bundle-version="1.1.4",
+ com.xored.fanide.ui;bundle-version="1.1.6",
+ com.xored.f4.fcode;bundle-version="1.1.6",
org.eclipse.core.filebuffers
Bundle-Vendor: Xored software, Inc.
Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/com.xored.f4.fcode.ui/pom.xml b/com.xored.f4.fcode.ui/pom.xml
index 814fc0eb..d696784e 100644
--- a/com.xored.f4.fcode.ui/pom.xml
+++ b/com.xored.f4.fcode.ui/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.f4.fcode.ui
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.f4.fcode/META-INF/MANIFEST.MF b/com.xored.f4.fcode/META-INF/MANIFEST.MF
index cf8ae43c..6a7e6b0f 100644
--- a/com.xored.f4.fcode/META-INF/MANIFEST.MF
+++ b/com.xored.f4.fcode/META-INF/MANIFEST.MF
@@ -2,14 +2,14 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: F4 Fcode
Bundle-SymbolicName: com.xored.f4.fcode;singleton:=true
-Bundle-Version: 1.1.4.qualifier
+Bundle-Version: 1.1.6.qualifier
Bundle-Vendor: Xored software, Inc.
Require-Bundle: org.eclipse.dltk.core,
- com.xored.fanide.core;bundle-version="1.1.4",
+ com.xored.fanide.core;bundle-version="1.1.6",
org.fantom.sys,
org.fantom.compiler,
- com.xored.f4.core;bundle-version="1.1.4",
- com.xored.f4.parser;bundle-version="1.1.4",
+ com.xored.f4.core;bundle-version="1.1.6",
+ com.xored.f4.parser;bundle-version="1.1.6",
org.eclipse.core.runtime,
org.eclipse.core.resources
Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/com.xored.f4.fcode/pom.xml b/com.xored.f4.fcode/pom.xml
index 70706787..98880d91 100644
--- a/com.xored.f4.fcode/pom.xml
+++ b/com.xored.f4.fcode/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.f4.fcode
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.f4.feature/feature.xml b/com.xored.f4.feature/feature.xml
index 0539af95..a173f814 100644
--- a/com.xored.f4.feature/feature.xml
+++ b/com.xored.f4.feature/feature.xml
@@ -2,7 +2,7 @@
@@ -18,12 +18,8 @@
%license
-
-
-
-
-
+
diff --git a/com.xored.f4.feature/pom.xml b/com.xored.f4.feature/pom.xml
index 77d53092..7ef8f9b4 100644
--- a/com.xored.f4.feature/pom.xml
+++ b/com.xored.f4.feature/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.f4.feature
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-feature
diff --git a/com.xored.f4.jdt.launching.ui/META-INF/MANIFEST.MF b/com.xored.f4.jdt.launching.ui/META-INF/MANIFEST.MF
index d56fb87d..0d2f2611 100644
--- a/com.xored.f4.jdt.launching.ui/META-INF/MANIFEST.MF
+++ b/com.xored.f4.jdt.launching.ui/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: F4 JDT Launching UI
Bundle-SymbolicName: com.xored.f4.jdt.launching.ui;singleton:=true
-Bundle-Version: 1.1.4.qualifier
+Bundle-Version: 1.1.6.qualifier
Bundle-Vendor: Xored software, Inc.
Require-Bundle: org.fantom.sys,
org.eclipse.debug.ui,
@@ -14,13 +14,13 @@ Require-Bundle: org.fantom.sys,
org.eclipse.swt,
org.eclipse.core.runtime,
org.fantom.fwt,
- com.xored.f4.jdt.launching;bundle-version="1.1.4",
- com.xored.f4.launching;bundle-version="1.1.4",
- com.xored.f4.model;bundle-version="1.1.4",
+ com.xored.f4.jdt.launching;bundle-version="1.1.6",
+ com.xored.f4.launching;bundle-version="1.1.6",
+ com.xored.f4.model;bundle-version="1.1.6",
org.eclipse.jdt.launching,
org.eclipse.jdt.debug,
org.eclipse.dltk.core,
- com.xored.fanide.core;bundle-version="1.1.4",
+ com.xored.fanide.core;bundle-version="1.1.6",
org.eclipse.jface.text,
org.eclipse.core.filebuffers,
org.eclipse.core.filesystem,
diff --git a/com.xored.f4.jdt.launching.ui/pom.xml b/com.xored.f4.jdt.launching.ui/pom.xml
index b7f17718..465d1f1b 100644
--- a/com.xored.f4.jdt.launching.ui/pom.xml
+++ b/com.xored.f4.jdt.launching.ui/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.f4.jdt.launching.ui
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.f4.jdt.launching/META-INF/MANIFEST.MF b/com.xored.f4.jdt.launching/META-INF/MANIFEST.MF
index 774809fb..ed5ad1fc 100644
--- a/com.xored.f4.jdt.launching/META-INF/MANIFEST.MF
+++ b/com.xored.f4.jdt.launching/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: F4 JDT Launching
Bundle-SymbolicName: com.xored.f4.jdt.launching;singleton:=true
-Bundle-Version: 1.1.4.qualifier
+Bundle-Version: 1.1.6.qualifier
Bundle-Vendor: Xored software, Inc.
Require-Bundle: org.fantom.sys,
org.eclipse.core.runtime,
diff --git a/com.xored.f4.jdt.launching/pom.xml b/com.xored.f4.jdt.launching/pom.xml
index c4dfad36..4315b79b 100644
--- a/com.xored.f4.jdt.launching/pom.xml
+++ b/com.xored.f4.jdt.launching/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.f4.jdt.launching
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.f4.launchEnv/META-INF/MANIFEST.MF b/com.xored.f4.launchEnv/META-INF/MANIFEST.MF
index 162da921..a55f471f 100644
--- a/com.xored.f4.launchEnv/META-INF/MANIFEST.MF
+++ b/com.xored.f4.launchEnv/META-INF/MANIFEST.MF
@@ -2,5 +2,5 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: F4 LaunchEnv
Bundle-SymbolicName: com.xored.f4.launchEnv;singleton:=true
-Bundle-Version: 1.1.4.qualifier
-Require-Bundle: org.fantom.sys;bundle-version="1.0.74"
+Bundle-Version: 1.1.6.qualifier
+Require-Bundle: org.fantom.sys;bundle-version="1.0.76"
diff --git a/com.xored.f4.launchEnv/pom.xml b/com.xored.f4.launchEnv/pom.xml
index 26626c73..5c1e54b7 100644
--- a/com.xored.f4.launchEnv/pom.xml
+++ b/com.xored.f4.launchEnv/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.f4.launchEnv
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.f4.launching/META-INF/MANIFEST.MF b/com.xored.f4.launching/META-INF/MANIFEST.MF
index 0bbbe137..939e1b92 100644
--- a/com.xored.f4.launching/META-INF/MANIFEST.MF
+++ b/com.xored.f4.launching/META-INF/MANIFEST.MF
@@ -2,17 +2,17 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: F4 Launching
Bundle-SymbolicName: com.xored.f4.launching;singleton:=true
-Bundle-Version: 1.1.4.qualifier
+Bundle-Version: 1.1.6.qualifier
Bundle-Vendor: xored software, Inc.
Require-Bundle: org.fantom.sys,
org.eclipse.core.runtime,
org.eclipse.dltk.launching,
org.eclipse.dltk.core,
- com.xored.fanide.core;bundle-version="1.1.4",
+ com.xored.fanide.core;bundle-version="1.1.6",
org.eclipse.debug.core,
org.eclipse.dltk.debug,
org.eclipse.core.variables,
org.eclipse.emf.ecore.xmi,
org.fantom.compiler,
- com.xored.f4.core;bundle-version="1.1.4",
- com.xored.f4.fcode;bundle-version="1.1.4"
+ com.xored.f4.core;bundle-version="1.1.6",
+ com.xored.f4.fcode;bundle-version="1.1.6"
diff --git a/com.xored.f4.launching/pom.xml b/com.xored.f4.launching/pom.xml
index 0ae2733e..0e4ac260 100644
--- a/com.xored.f4.launching/pom.xml
+++ b/com.xored.f4.launching/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.f4.launching
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.f4.model/META-INF/MANIFEST.MF b/com.xored.f4.model/META-INF/MANIFEST.MF
index 74514a19..8825075d 100644
--- a/com.xored.f4.model/META-INF/MANIFEST.MF
+++ b/com.xored.f4.model/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: F4 Model
Bundle-SymbolicName: com.xored.f4.model;singleton:=true
-Bundle-Version: 1.1.4.qualifier
+Bundle-Version: 1.1.6.qualifier
Bundle-Vendor: xored software, Inc.
Require-Bundle: org.fantom.sys,
org.fantom.compiler,
diff --git a/com.xored.f4.model/f4model.pod b/com.xored.f4.model/f4model.pod
index 77f5f721..aec2fa35 100644
Binary files a/com.xored.f4.model/f4model.pod and b/com.xored.f4.model/f4model.pod differ
diff --git a/com.xored.f4.model/fan/model/IFanNamespace.fan b/com.xored.f4.model/fan/model/IFanNamespace.fan
index bc659d9c..507fec20 100644
--- a/com.xored.f4.model/fan/model/IFanNamespace.fan
+++ b/com.xored.f4.model/fan/model/IFanNamespace.fan
@@ -1,101 +1,117 @@
-abstract class IFanNamespace
-{
- abstract IFanPod currPod()
- abstract Str[] podNames()
- abstract IFanPod? findPod(Str name)
- virtual IFanType? findType(Str name)
- {
- if(name.isEmpty) return null
- if(name[-1] == '?') name = name[0..-2]
- //special handling for Lists and Maps
- IFanType? result := trySpecial(name)
- if(result != null) return result
-
- index := name.index("::")
- Str? pod := null
- if(index != null)
- {
- pod = name[0..")
+ if (idx != null) {
+ retType := findType(name[idx+2..<-1])
+ if (retType != null)
+ // there doesn't seem to be a need to parameterise the arguments too
+ func = func.parameterize(["sys::R":retType])
+ }
+ return func
+ }
+
+ return null
+ }
}
\ No newline at end of file
diff --git a/com.xored.f4.model/fan/model/IFanType.fan b/com.xored.f4.model/fan/model/IFanType.fan
index 6d24ca1c..25f4e103 100644
--- a/com.xored.f4.model/fan/model/IFanType.fan
+++ b/com.xored.f4.model/fan/model/IFanType.fan
@@ -228,25 +228,27 @@ const mixin IFanType : DltkModelElement
addSlotsTo(ns,result)
return result.vals
}
-
- private Void addSlotsTo(IFanNamespace ns, Str:IFanSlot map,Str[] excluded := [,])
- {
- excluded.add(qname)
- //deep search
- if (!excluded.contains("sys::Obj"))
- ns.findType("sys::Obj")?.addSlotsTo(ns,map,excluded)
- inheritance.each |t|
- {
- type := ns.findType(t)
- if(type == null) return
- if (!excluded.contains(type.qname))
- type?.addSlotsTo(ns,map,excluded)
- }
- slotsMap.each |IFanSlot slot, Str name| {
- if( !map.containsKey(name))
- {
- map[name] = slot
- }
- }
- }
+
+
+ private Void addSlotsTo(IFanNamespace ns, Str:IFanSlot map, Str[] excluded := [,]) {
+ excluded.add(qname)
+
+ // add *our* slots first so they don't get overridden by Obj
+ slotsMap.each |IFanSlot slot, Str name| {
+ if (!map.containsKey(name)) {
+ map[name] = slot
+ }
+ }
+
+ inheritance.each |t| {
+ type := ns.findType(t)
+ if (type == null) return
+ if (!excluded.contains(type.qname))
+ type.addSlotsTo(ns, map, excluded)
+ }
+
+ // always include Obj, think of mixins et al
+ if (!excluded.contains("sys::Obj"))
+ ns.findType("sys::Obj")?.addSlotsTo(ns, map, excluded)
+ }
}
\ No newline at end of file
diff --git a/com.xored.f4.model/pom.xml b/com.xored.f4.model/pom.xml
index 2eb7e9b8..71d526e8 100644
--- a/com.xored.f4.model/pom.xml
+++ b/com.xored.f4.model/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.f4.model
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.f4.parser/META-INF/MANIFEST.MF b/com.xored.f4.parser/META-INF/MANIFEST.MF
index 4bffaa43..d1c286ad 100644
--- a/com.xored.f4.parser/META-INF/MANIFEST.MF
+++ b/com.xored.f4.parser/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: F4 Parser
Bundle-SymbolicName: com.xored.f4.parser;singleton:=true
-Bundle-Version: 1.1.4.qualifier
+Bundle-Version: 1.1.6.qualifier
Require-Bundle: org.fantom.sys,
- com.xored.f4.model;bundle-version="1.1.4"
+ com.xored.f4.model;bundle-version="1.1.6"
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
diff --git a/com.xored.f4.parser/f4parser.pod b/com.xored.f4.parser/f4parser.pod
index 55f916cf..3c0be935 100644
Binary files a/com.xored.f4.parser/f4parser.pod and b/com.xored.f4.parser/f4parser.pod differ
diff --git a/com.xored.f4.parser/fan/ast/Statements.fan b/com.xored.f4.parser/fan/ast/Statements.fan
index 81e6dea1..a1a719c9 100644
--- a/com.xored.f4.parser/fan/ast/Statements.fan
+++ b/com.xored.f4.parser/fan/ast/Statements.fan
@@ -199,8 +199,9 @@ const class CatchStmt : Stmt
{
if (v.enterNode(this))
{
- errVar?.accept(v)
block.accept(v)
+ // make sure to accept the Err var *inside* the catch block, to make it available
+ errVar?.accept(v)
v.exitNode(this)
}
}
diff --git a/com.xored.f4.parser/fan/parser/Parser.fan b/com.xored.f4.parser/fan/parser/Parser.fan
index 94cc6707..a1de48e3 100644
--- a/com.xored.f4.parser/fan/parser/Parser.fan
+++ b/com.xored.f4.parser/fan/parser/Parser.fan
@@ -1048,22 +1048,48 @@ class Parser : AstFactory
return operand
}
- Expr shortcut(Int start, Int end, ExprId id, Str methodName, Expr left, Expr? right, TokenVal op)
- {
- IFanType? rt := null
- if (left.resolvedType != null)
- {
- method := left.resolvedType.method(methodName, false)
- if (method == null)
- err(locOf(op), ProblemKind.parser_methodNotFound, [left.resolvedType.name + "." + methodName])
- else
- {
- rt = ns.findType(method.of)
- }
- }
- if (right == null) return UnaryExpr(start, end, left, id, rt)
- return BinaryExpr(start, end, left, right, id, rt)
- }
+ Expr shortcut(Int start, Int end, ExprId id, Str methodName, Expr left, Expr? right, TokenVal op) {
+
+ // DateTime.minus(Duration) = DateTime
+ // DateTime.minusDateTime(DateTime) = Duration
+ // problem is, we have to infer which method to use given the 2nd arg type
+ // it's a bit of a fath, but do-able...
+
+ retType := null as IFanType
+
+ if (left.resolvedType != null) {
+ opType := left.resolvedType
+ method := null as IFanMethod
+
+ if (right?.resolvedType != null && _opMethodPrefixes.contains(methodName)) {
+ // do the dance, looking for the actual method the shortcut corresponds to
+ method = opType.allSlots(ns).find |slot| {
+ if (slot.isMethod) {
+ mslot := (IFanMethod) slot
+ param := (mslot.params.size > 0 ? ns.findType(mslot.params.first.of) : null) as IFanType
+ if (param?.qname == right.resolvedType.qname)
+ return true
+ }
+ return false
+ }
+
+ } else
+ // for normal ops, just use the method direct
+ method = opType.method(methodName, false)
+
+ if (method != null)
+ retType = ns.findType(method.of)
+ else
+ err(locOf(op), ProblemKind.parser_methodNotFound, [left.resolvedType.name + "." + methodName])
+ }
+
+ return right == null
+ ? UnaryExpr (start, end, left, id, retType)
+ : BinaryExpr(start, end, left, right, id, retType)
+ }
+
+ ** see https://fantom.org/doc/docLang/Methods#operators
+ private static const Str[] _opMethodPrefixes := "plus minus mult div mod".split
//////////////////////////////////////////////////////////////////////////
// Term Expr
diff --git a/com.xored.f4.parser/pom.xml b/com.xored.f4.parser/pom.xml
index 10ae58e4..4f3402d6 100644
--- a/com.xored.f4.parser/pom.xml
+++ b/com.xored.f4.parser/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.f4.parser
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.f4.pathEnv/META-INF/MANIFEST.MF b/com.xored.f4.pathEnv/META-INF/MANIFEST.MF
index 1e1fc3aa..0e119c80 100644
--- a/com.xored.f4.pathEnv/META-INF/MANIFEST.MF
+++ b/com.xored.f4.pathEnv/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: F4 PathEnv
Bundle-SymbolicName: com.xored.f4.pathEnv;singleton:=true
-Bundle-Version: 1.1.4.qualifier
+Bundle-Version: 1.1.6.qualifier
Require-Bundle: org.fantom.sys,
com.xored.f4.core,
com.xored.f4.builder.ui,
diff --git a/com.xored.f4.pathEnv/pom.xml b/com.xored.f4.pathEnv/pom.xml
index a9197237..ef26293f 100644
--- a/com.xored.f4.pathEnv/pom.xml
+++ b/com.xored.f4.pathEnv/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.f4.pathEnv
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.f4.platform/META-INF/MANIFEST.MF b/com.xored.f4.platform/META-INF/MANIFEST.MF
index 53d99e04..605bb251 100644
--- a/com.xored.f4.platform/META-INF/MANIFEST.MF
+++ b/com.xored.f4.platform/META-INF/MANIFEST.MF
@@ -4,7 +4,7 @@ Bundle-Localization: plugin
Bundle-Name: %pluginName
Eclipse-BundleShape: dir
Bundle-SymbolicName: com.xored.f4.platform;singleton:=true
-Bundle-Version: 1.1.4.qualifier
+Bundle-Version: 1.1.6.qualifier
Bundle-Vendor: %providerName
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime
diff --git a/com.xored.f4.platform/about.ini b/com.xored.f4.platform/about.ini
index 72f49508..85b614ba 100644
--- a/com.xored.f4.platform/about.ini
+++ b/com.xored.f4.platform/about.ini
@@ -11,7 +11,7 @@ featureImage=featureImage.png
aboutText=F4 Fantom IDE \n\
\n\
-Version: 1.1.4\n\
+Version: 1.1.6\n\
\n\
Copyright (c) 2009-2020 Xored Software, Inc. All rights reserved.\n\
\n\
diff --git a/com.xored.f4.platform/pom.xml b/com.xored.f4.platform/pom.xml
index b5da760c..807d440e 100644
--- a/com.xored.f4.platform/pom.xml
+++ b/com.xored.f4.platform/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.f4.platform
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.f4.search/META-INF/MANIFEST.MF b/com.xored.f4.search/META-INF/MANIFEST.MF
index f4cb0d75..563bf741 100644
--- a/com.xored.f4.search/META-INF/MANIFEST.MF
+++ b/com.xored.f4.search/META-INF/MANIFEST.MF
@@ -2,14 +2,14 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: F4 Search
Bundle-SymbolicName: com.xored.f4.search;singleton:=true
-Bundle-Version: 1.1.4.qualifier
+Bundle-Version: 1.1.6.qualifier
Bundle-Vendor: Xored software, Inc.
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.core.resources,
org.fantom.sys,
- com.xored.f4.parser;bundle-version="1.1.4",
- com.xored.f4.core;bundle-version="1.1.4",
- com.xored.f4.model;bundle-version="1.1.4",
+ com.xored.f4.parser;bundle-version="1.1.6",
+ com.xored.f4.core;bundle-version="1.1.6",
+ com.xored.f4.model;bundle-version="1.1.6",
org.eclipse.dltk.core,
com.xored.fanide.core
diff --git a/com.xored.f4.search/f4search.pod b/com.xored.f4.search/f4search.pod
index 6581d7bb..29cbc206 100644
Binary files a/com.xored.f4.search/f4search.pod and b/com.xored.f4.search/f4search.pod differ
diff --git a/com.xored.f4.search/pom.xml b/com.xored.f4.search/pom.xml
index 790e0a70..f8951cf6 100644
--- a/com.xored.f4.search/pom.xml
+++ b/com.xored.f4.search/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.f4.search
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.f4.testing/META-INF/MANIFEST.MF b/com.xored.f4.testing/META-INF/MANIFEST.MF
index 404a5b40..016e6deb 100644
--- a/com.xored.f4.testing/META-INF/MANIFEST.MF
+++ b/com.xored.f4.testing/META-INF/MANIFEST.MF
@@ -2,18 +2,18 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: F4 Testing
Bundle-SymbolicName: com.xored.f4.testing;singleton:=true
-Bundle-Version: 1.1.4.qualifier
+Bundle-Version: 1.1.6.qualifier
Bundle-Vendor: Xored software, Inc.
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Require-Bundle: org.fantom.sys,
org.eclipse.debug.core,
- com.xored.f4.jdt.launching;bundle-version="1.1.4",
- com.xored.f4.debug.ui;bundle-version="1.1.4",
- com.xored.f4.launching;bundle-version="1.1.4",
- com.xored.f4.parser;bundle-version="1.1.4",
- com.xored.f4.core;bundle-version="1.1.4",
- com.xored.f4.model;bundle-version="1.1.4",
+ com.xored.f4.jdt.launching;bundle-version="1.1.6",
+ com.xored.f4.debug.ui;bundle-version="1.1.6",
+ com.xored.f4.launching;bundle-version="1.1.6",
+ com.xored.f4.parser;bundle-version="1.1.6",
+ com.xored.f4.core;bundle-version="1.1.6",
+ com.xored.f4.model;bundle-version="1.1.6",
org.eclipse.dltk.testing,
org.eclipse.jface,
org.eclipse.debug.ui,
diff --git a/com.xored.f4.testing/pom.xml b/com.xored.f4.testing/pom.xml
index c56e3c0f..f4f857c7 100644
--- a/com.xored.f4.testing/pom.xml
+++ b/com.xored.f4.testing/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.f4.testing
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.f4.ui.core/META-INF/MANIFEST.MF b/com.xored.f4.ui.core/META-INF/MANIFEST.MF
index f41de486..37371f69 100644
--- a/com.xored.f4.ui.core/META-INF/MANIFEST.MF
+++ b/com.xored.f4.ui.core/META-INF/MANIFEST.MF
@@ -2,12 +2,12 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: F4 UI Core
Bundle-SymbolicName: com.xored.f4.ui.core;singleton:=true
-Bundle-Version: 1.1.4.qualifier
+Bundle-Version: 1.1.6.qualifier
Require-Bundle: org.eclipse.dltk.ui;bundle-version="3.0.0",
org.fantom.sys,
org.eclipse.ui,
org.eclipse.core.runtime,
- com.xored.fanide.ui;bundle-version="1.1.4",
+ com.xored.fanide.ui;bundle-version="1.1.6",
org.eclipse.jface.text,
org.eclipse.dltk.core;bundle-version="3.0.0",
org.eclipse.core.resources,
@@ -17,7 +17,7 @@ Require-Bundle: org.eclipse.dltk.ui;bundle-version="3.0.0",
org.eclipse.core.filebuffers,
org.eclipse.ui.console,
org.eclipse.ui.editors,
- com.xored.fanide.core;bundle-version="1.1.4",
+ com.xored.fanide.core;bundle-version="1.1.6",
com.ibm.icu,
org.eclipse.dltk.launching;bundle-version="3.0.0"
Bundle-Activator: com.xored.f4.ui.core.F4UIPlugin
diff --git a/com.xored.f4.ui.core/pom.xml b/com.xored.f4.ui.core/pom.xml
index 3a2c44c0..9da46113 100644
--- a/com.xored.f4.ui.core/pom.xml
+++ b/com.xored.f4.ui.core/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.f4.ui.core
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.f4.ui.jdt/META-INF/MANIFEST.MF b/com.xored.f4.ui.jdt/META-INF/MANIFEST.MF
index 28ca2a48..9921c604 100644
--- a/com.xored.f4.ui.jdt/META-INF/MANIFEST.MF
+++ b/com.xored.f4.ui.jdt/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: F4 UI JDT
Bundle-SymbolicName: com.xored.f4.ui.jdt;singleton:=true
-Bundle-Version: 1.1.4.qualifier
+Bundle-Version: 1.1.6.qualifier
Bundle-Vendor: Xored software, Inc.
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Require-Bundle: org.eclipse.core.resources,
@@ -16,7 +16,7 @@ Require-Bundle: org.eclipse.core.resources,
org.eclipse.ui,
org.eclipse.debug.core,
org.fantom.sys,
- com.xored.f4.jdt.launching;bundle-version="1.1.4",
+ com.xored.f4.jdt.launching;bundle-version="1.1.6",
org.eclipse.dltk.core,
org.eclipse.dltk.ui
Import-Package: org.eclipse.dltk.ui
diff --git a/com.xored.f4.ui.jdt/pom.xml b/com.xored.f4.ui.jdt/pom.xml
index 56fa4a40..ddbca0d2 100644
--- a/com.xored.f4.ui.jdt/pom.xml
+++ b/com.xored.f4.ui.jdt/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.f4.ui.jdt
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.f4.ui.text/META-INF/MANIFEST.MF b/com.xored.f4.ui.text/META-INF/MANIFEST.MF
index ae88c11e..f5f4750b 100644
--- a/com.xored.f4.ui.text/META-INF/MANIFEST.MF
+++ b/com.xored.f4.ui.text/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: F4 UI Text
Bundle-SymbolicName: com.xored.f4.ui.text;singleton:=true
-Bundle-Version: 1.1.4.qualifier
+Bundle-Version: 1.1.6.qualifier
Bundle-Vendor: Xored software, Inc.
Bundle-Localization: plugin
Require-Bundle: org.eclipse.core.runtime,
@@ -16,11 +16,11 @@ Require-Bundle: org.eclipse.core.runtime,
org.fantom.sys,
org.eclipse.search,
org.fantom.fandoc,
- com.xored.f4.parser;bundle-version="1.1.4",
- com.xored.f4.model;bundle-version="1.1.4",
- com.xored.f4.core;bundle-version="1.1.4",
- com.xored.f4.ui.core;bundle-version="1.1.4",
- com.xored.fanide.ui;bundle-version="1.1.4",
+ com.xored.f4.parser;bundle-version="1.1.6",
+ com.xored.f4.model;bundle-version="1.1.6",
+ com.xored.f4.core;bundle-version="1.1.6",
+ com.xored.f4.ui.core;bundle-version="1.1.6",
+ com.xored.fanide.ui;bundle-version="1.1.6",
org.eclipse.core.filesystem,
com.ibm.icu,
org.eclipse.ui.ide,
diff --git a/com.xored.f4.ui.text/f4uiText.pod b/com.xored.f4.ui.text/f4uiText.pod
index 5ed2e968..d2701405 100644
Binary files a/com.xored.f4.ui.text/f4uiText.pod and b/com.xored.f4.ui.text/f4uiText.pod differ
diff --git a/com.xored.f4.ui.text/fan/contentassist/CompletionProvider.fan b/com.xored.f4.ui.text/fan/contentassist/CompletionProvider.fan
index c3286be9..542164c1 100644
--- a/com.xored.f4.ui.text/fan/contentassist/CompletionProvider.fan
+++ b/com.xored.f4.ui.text/fan/contentassist/CompletionProvider.fan
@@ -72,10 +72,13 @@ abstract class CompletionProvider {
** Helper method to report bunch of slots
**
protected Void reportSlots(IFanSlot[] slots) {
- slots = slots.findAll { it.name.lower.startsWith(prefix.lower) }
+ prefixLower := prefix.lower
+
slots.each |slot| {
- if (slot.isField) reportField(slot)
- else if (slot.isMethod) reportMethod(slot)
+ if (prefixLower.isEmpty || slot.name.lower.startsWith(prefixLower)) {
+ if (slot.isField ) reportField (slot)
+ if (slot.isMethod) reportMethod(slot)
+ }
}
}
@@ -87,11 +90,10 @@ abstract class CompletionProvider {
reporter.report(createProposal(ProposeKind.field, field.name, field.me, reporter.computeCaseRelevance(this.prefix, field.name)))
}
- protected Void reportMethod(IFanMethod method, Str? mname := null) {
- params := method.params
-
+ protected Void reportMethod(IFanMethod method, Str? mname := null) {
if (reporter.ignores(ProposeKind.method)) return
+ params := method.params
required := params.findIndex { it.hasDefault }
if (required == null) { required = params.size }
diff --git a/com.xored.f4.ui.text/fan/contentassist/DotCompletionProvider.fan b/com.xored.f4.ui.text/fan/contentassist/DotCompletionProvider.fan
index 0c29c8da..211f4f61 100644
--- a/com.xored.f4.ui.text/fan/contentassist/DotCompletionProvider.fan
+++ b/com.xored.f4.ui.text/fan/contentassist/DotCompletionProvider.fan
@@ -59,7 +59,8 @@ class DotCompletionProvider : CompletionProvider {
}
reportSlots(slots)
-
+
+ // given reportSlots adds in slots for Obj, I believe we should always have a ctor - SlimerDude July 2021
if (isStatic && !slots.any { it.isCtor })
reportDefaultCtor
diff --git a/com.xored.f4.ui.text/fan/contentassist/FanMethodCompletionProposal.fan b/com.xored.f4.ui.text/fan/contentassist/FanMethodCompletionProposal.fan
index 270ab519..5fbb806e 100644
--- a/com.xored.f4.ui.text/fan/contentassist/FanMethodCompletionProposal.fan
+++ b/com.xored.f4.ui.text/fan/contentassist/FanMethodCompletionProposal.fan
@@ -108,9 +108,8 @@ class FanMethodCompletionProposal : ScriptMethodCompletionProposal {
argumentOffset += 1
}
- buffer.add("{ }")
- replacementBuffer.addArgument(argumentOffset, 1)
- // one space only
+ buffer.add("{ }")
+ replacementBuffer.addArgument(argumentOffset, 0)
return buffer.toStr
}
diff --git a/com.xored.f4.ui.text/pom.xml b/com.xored.f4.ui.text/pom.xml
index f93e5359..e7b72bea 100644
--- a/com.xored.f4.ui.text/pom.xml
+++ b/com.xored.f4.ui.text/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.f4.ui.text
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.fanide.core/META-INF/MANIFEST.MF b/com.xored.fanide.core/META-INF/MANIFEST.MF
index e4fa60fd..2ed514bd 100644
--- a/com.xored.fanide.core/META-INF/MANIFEST.MF
+++ b/com.xored.fanide.core/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: com.xored.fanide.core;singleton:=true
-Bundle-Version: 1.1.4.qualifier
+Bundle-Version: 1.1.6.qualifier
Bundle-Activator: com.xored.fanide.core.FanCore
Bundle-Vendor: %providerName
Require-Bundle: org.eclipse.core.runtime,
diff --git a/com.xored.fanide.core/pom.xml b/com.xored.fanide.core/pom.xml
index 55f9827a..b783a789 100644
--- a/com.xored.fanide.core/pom.xml
+++ b/com.xored.fanide.core/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.fanide.core
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.fanide.ui/META-INF/MANIFEST.MF b/com.xored.fanide.ui/META-INF/MANIFEST.MF
index 9a52171a..66576a12 100644
--- a/com.xored.fanide.ui/META-INF/MANIFEST.MF
+++ b/com.xored.fanide.ui/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: com.xored.fanide.ui;singleton:=true
-Bundle-Version: 1.1.4.qualifier
+Bundle-Version: 1.1.6.qualifier
Bundle-Activator: com.xored.fanide.internal.ui.FanUI
Bundle-Vendor: %pluginProvider
Bundle-Localization: plugin
@@ -23,7 +23,7 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.dltk.launching,
org.eclipse.dltk.debug.ui,
org.eclipse.dltk.ui,
- com.xored.fanide.core;bundle-version="1.1.4",
+ com.xored.fanide.core;bundle-version="1.1.6",
org.eclipse.core.filesystem,
org.fantom,
org.eclipse.jdt.core,
diff --git a/com.xored.fanide.ui/pom.xml b/com.xored.fanide.ui/pom.xml
index ff2e3b71..8db53de9 100644
--- a/com.xored.fanide.ui/pom.xml
+++ b/com.xored.fanide.ui/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
com.xored.fanide.ui
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-plugin
diff --git a/com.xored.fanide.ui/src/com/xored/fanide/internal/ui/preferences/FanEditorColoringConfigurationBlock.java b/com.xored.fanide.ui/src/com/xored/fanide/internal/ui/preferences/FanEditorColoringConfigurationBlock.java
index 8044156c..223b40d7 100644
--- a/com.xored.fanide.ui/src/com/xored/fanide/internal/ui/preferences/FanEditorColoringConfigurationBlock.java
+++ b/com.xored.fanide.ui/src/com/xored/fanide/internal/ui/preferences/FanEditorColoringConfigurationBlock.java
@@ -16,6 +16,7 @@
import org.eclipse.dltk.ui.preferences.IPreferenceConfigurationBlock;
import org.eclipse.dltk.ui.preferences.OverlayPreferenceStore;
import org.eclipse.dltk.ui.preferences.PreferencesMessages;
+import org.eclipse.dltk.ui.text.DLTKColorConstants;
import org.eclipse.dltk.ui.text.IColorManager;
import org.eclipse.dltk.ui.text.ScriptSourceViewerConfiguration;
import org.eclipse.dltk.ui.text.ScriptTextTools;
@@ -113,7 +114,15 @@ public class FanEditorColoringConfigurationBlock extends
//WTFs
{ PreferencesMessages.DLTKEditorPreferencePage_decorators,
FanPreferenceConstants.EDITOR_DECORATOR_COLOR,
- sCoreCategory }
+ sCoreCategory },
+
+ // The Missing Colour for Dark Mode! - SlimerDude, July 2021
+ { "Default", DLTKColorConstants.DLTK_DEFAULT, sCoreCategory }
+
+ // these other colours don't seem to be used - SlimerDude, July 2021
+// { "x-Operator", DLTKColorConstants.DLTK_OPERATOR, sCoreCategory },
+// { "x-Argument", DLTKColorConstants.DLTK_ARGUMENT, sCoreCategory },
+// { "x-Base Class", DLTKColorConstants.DLTK_BASE_CLASS, sCoreCategory }
};
diff --git a/com.xored.fanide.ui/src/com/xored/fanide/internal/ui/preferences/PreviewFile.txt b/com.xored.fanide.ui/src/com/xored/fanide/internal/ui/preferences/PreviewFile.txt
index ac697bff..0a86f1d5 100644
--- a/com.xored.fanide.ui/src/com/xored/fanide/internal/ui/preferences/PreviewFile.txt
+++ b/com.xored.fanide.ui/src/com/xored/fanide/internal/ui/preferences/PreviewFile.txt
@@ -1,20 +1,17 @@
#!empty
** TODO: Something
-class Hello
-{
+class Hello : Obj {
Str member := "value"
- static Void main()
- {
+
+ static Void main(Str[] args) {
localVar := "world"
echo("hello ${localVar}!")
}
/* This comment may span multiple lines. */
- Int func()
- {
+ Int func() {
// FIXME: Nothing
- echo(Str <|no \ or $ escapes need, and
- multi-line works too|>)
- return 4
+ echo(Str<|no \ or $ escapes needed|>)
+ return 4 + 2
}
-}
\ No newline at end of file
+}
diff --git a/f4tests/pom-server.xml b/f4tests/pom-server.xml
index e4e10e96..ac4350f8 100644
--- a/f4tests/pom-server.xml
+++ b/f4tests/pom-server.xml
@@ -160,7 +160,7 @@
1.1.1-SNAPSHOT
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
diff --git a/pom.xml b/pom.xml
index 399248af..56e6615c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -113,22 +113,18 @@
p2
-
win32
win32
- x86
+ x86_64
+ -->
win32
win32
- x86_64
+ x86
-
linux
gtk
@@ -144,7 +140,7 @@
cocoa
x86_64
-
diff --git a/product/category.xml b/product/category.xml
index 28c20cb1..d68a7067 100644
--- a/product/category.xml
+++ b/product/category.xml
@@ -3,13 +3,13 @@
F4 Fantom IDE update site
-
+
-
+
-
+
diff --git a/product/com.xored.f4.ide.p2.inf b/product/com.xored.f4.ide.p2.inf
index 9912c4f4..e6d42d89 100644
--- a/product/com.xored.f4.ide.p2.inf
+++ b/product/com.xored.f4.ide.p2.inf
@@ -3,6 +3,4 @@ instructions.configure=\
addRepository(type:1,location:http${#58}//download.eclipse.org/releases/photon,name:Photon);\
addRepository(type:0,location:http${#58}//download.eclipse.org/eclipse/updates/4.8,name:The Eclipse Project Updates);\
addRepository(type:1,location:http${#58}//download.eclipse.org/eclipse/updates/4.8,name:The Eclipse Project Updates);\
- addRepository(type:0,location:http${#58}//download.xored.com/f4/updates/stable,name:F4 Update Site);\
- addRepository(type:1,location:http${#58}//download.xored.com/f4/updates/stable,name:F4 Update Site);\
setProgramProperty(propName:osgi.instance.area.default,propValue:@user.home/f4workspace);
diff --git a/product/com.xored.f4.ide.product b/product/com.xored.f4.ide.product
index bb9112ce..d607fece 100644
--- a/product/com.xored.f4.ide.product
+++ b/product/com.xored.f4.ide.product
@@ -1,7 +1,7 @@
-
+
diff --git a/product/pom.xml b/product/pom.xml
index c38c38ff..213eaddb 100644
--- a/product/pom.xml
+++ b/product/pom.xml
@@ -9,7 +9,7 @@
com.xored.f4
product
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-repository
diff --git a/repository/category.xml b/repository/category.xml
index b20a0051..5fd4026a 100644
--- a/repository/category.xml
+++ b/repository/category.xml
@@ -3,14 +3,14 @@
F4 Fantom IDE update site
-
+
-
+
-
+
diff --git a/repository/pom.xml b/repository/pom.xml
index a7752093..7ccd747b 100644
--- a/repository/pom.xml
+++ b/repository/pom.xml
@@ -9,6 +9,6 @@
com.xored.f4
repository
- 1.1.4-SNAPSHOT
+ 1.1.6-SNAPSHOT
eclipse-repository