first commit

This commit is contained in:
2026-06-21 21:05:24 -05:00
commit 973db5f00a
9 changed files with 559 additions and 0 deletions

5
Tesses.CrossLisp.Runtime/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
.DS_Store
bin
obj
publish
thumbs.db

View File

@@ -0,0 +1,8 @@
{
"$schema": "https:\/\/crosslang.tesseslanguage.com\/\/schema\/cross-json-schema.json",
"info": {
"type": "lib"
},
"name": "Tesses.CrossLisp.Runtime",
"version": "1.0.0.0-prod"
}

View File

@@ -0,0 +1,462 @@
func CrossLisp.isString(v)
{
if(!TypeIsList(v)) return false;
if(v.Length < 2) return false;
return v[0] == "$string";
}
func CrossLisp.getString(v)
{
if(!CrossLisp.isString(v)) return "";
return v[1];
}
func CrossLisp.asCrossLangList(val)
{
if(TypeIsLong(val)) return val.ToString();
if(TypeIsDouble(val)) return val.ToString();
if(TypeIsString(val)) return val.Escape(true);
if(TypeIsList(val))
{
var str = "[";
for(var i = 0; i < val.Length; i++)
{
if(i > 0)
str += ", ";
str += CrossLisp.asCrossLangList(val[i]);
}
return str + "]";
}
return "null";
}
func CrossLisp.toCrossLangExpression(val)
{
if(val == "nil") return "[]";
if(TypeIsLong(val)) return val.ToString();
if(TypeIsDouble(val)) return val.ToString();
if(TypeIsString(val)) return val;
if(TypeIsList(val))
{
if(val.Length == 0) return "[]";
switch(val[0])
{
case "+":
{
var fnCall = "(";
if(val.Length == 1)
fnCall += "0";
for(var i = 1; i < val.Length; i++)
{
if(i > 1)
fnCall += " + ";
fnCall += CrossLisp.toCrossLangExpression(val[i]);
}
return fnCall + ")";
}
break;
case "-":
{
var fnCall = "(";
if(val.Length == 1)
fnCall += "0";
for(var i = 1; i < val.Length; i++)
{
if(i > 1)
fnCall += " - ";
fnCall += CrossLisp.toCrossLangExpression(val[i]);
}
return fnCall + ")";
}
break;
case "*":
{
var fnCall = "(";
if(val.Length == 1)
fnCall += "0";
for(var i = 1; i < val.Length; i++)
{
if(i > 1)
fnCall += " * ";
fnCall += CrossLisp.toCrossLangExpression(val[i]);
}
return fnCall + ")";
}
break;
case "/":
{
var fnCall = "(";
if(val.Length == 1)
fnCall += "0";
for(var i = 1; i < val.Length; i++)
{
if(i > 1)
fnCall += " / ";
fnCall += CrossLisp.toCrossLangExpression(val[i]);
}
return fnCall + ")";
}
break;
case "%":
{
var fnCall = "(";
if(val.Length == 1)
fnCall += "0";
for(var i = 1; i < val.Length; i++)
{
if(i > 1)
fnCall += " % ";
fnCall += CrossLisp.toCrossLangExpression(val[i]);
}
return fnCall + ")";
}
break;
case "quote":
{
if(val.Count > 1)
return CrossLisp.asCrossLangList(val[1]);
}
break;
case "call":
{
if(val.Length >= 3 && CrossLisp.isString(val[2]))
{
var fnCall = "(" + CrossLisp.toCrossLangExpression(val[1]) + $").{CrossLisp.getString(val[2])}(";
for(var i = 3; i < val.Length; i++)
{
if(i > 3)
fnCall += ", ";
fnCall += CrossLisp.toCrossLangExpression(val[i]);
}
return fnCall + ")";
}
//(call Console "WriteLine" args...)
}
case "eval":
{
if(val.Length == 2)
{
return "VM.Eval(\"return \" + CrossLisp.toCrossLangExpression(" + CrossLisp.toCrossLangExpression(val[1]) + ") + \";\")";
}
}
break;
case "setq":
{
//(setq val 42)
if(val.Length == 3 && TypeIsString(name))
{
return "(" + name + "=" + CrossLisp.toCrossLangExpression(val[2]) + ")";
}
}
break;
case "dict":
{
var dict = "{";
for(var i = 1; i < val.Length; i++)
{
if(i > 1)
dict += ", ";
if(TypeIsList(val[i]) && val[i].Length == 2 && TypeIsString(val[i][0]))
{
dict += val[i][0] + " = " + CrossLisp.toCrossLangExpression(val[i][1]);
}
else {
throw "Must look like this (dict (key1 value) (key2 value))";
}
}
return dict + "}";
}
break;
case "$string":
{
if(val.Length == 2)
{
return val[1].Escape(true);
}
}
break;
default:
{
var fnCall = val[0] + "(";
for(var i = 1; i < val.Length; i++)
{
if(i > 1)
fnCall += ", ";
fnCall += CrossLisp.toCrossLangExpression(val[i]);
}
return fnCall + ")";
}
break;
}
}
return "[]";
}
func CrossLisp.toCrossLangText(list)
{
var code = "";
each(var item : list)
{
if(TypeIsList(item) && item.Length > 0)
{
if(item[0] == "defun")
{
if(TypeIsString(item[1]))
{
var hasDoc = false;
if(CrossLisp.isString(item[3]))
{
hasDoc=true;
code += "\n/^ " + CrossLisp.getString(item[3]).Replace("^","^^") + " ^/\n";
}
code += $"func {item[1]}(";
if(TypeIsList(item[2]))
{
for(var i = 0; i < item[2].Length; i++)
{
if(i > 0) code += ", ";
code += item[2][i];
}
}
code += "){";
for(var i = hasDoc ? 4 : 3; i < item.Length; i++)
{
if(i + 1 == item.Length)
code += "return ";
code += CrossLisp.toCrossLangExpression(item[i]);
code += ";";
}
code += "}";
}
}
}
}
return code;
}
func CrossLisp.parseLisp(text)
{
//(+ "Hi" 42)
//["+",["$string","Hi"], 42]
//(+ 'hi 42)
//["+",["quote",["hi"]],42]
var builder = "";
var tokens = [];
func flush()
{
if(builder.Length > 0) {
if(builder[0] >= '0' && builder[0] <= '9')
{
if(builder.Contains("."))
{
const dbl = ParseDouble(builder);
tokens.Add({
type = "ident",
value = dbl
});
}
else {
const lng = ParseLong(builder);
tokens.Add({
type = "ident",
value = lng
});
}
}
else {
tokens.Add({
type = "ident",
value = builder
});
}
builder = "";
}
}
for(var i = 0; i < text.Length; i++)
{
switch(text[i])
{
case '(':
{
flush();
tokens.Add({
type="("
});
}
break;
case ')':
{
flush();
tokens.Add({
type=")"
});
}
break;
case '\'':
{
flush();
tokens.Add({
type="'"
});
}
break;
break;
case '\\':
builder += text[++i];
break;
case '\"':
{
flush();
i++;
var strtext = "";
for(; (i < text.Length) && text[i] != '\"'; i++)
{
if(text[i] == '\\')
{
i++;
if(i < text.Length)
{
if(text[i] == 'n')
{
strtext += "\n";
}
else if(text[i] == 'r')
{
strtext += "\r";
}
else if(text[i] == 't')
{
strtext += "\t";
}
else if(text[i] == 'v')
{
strtext += "\v";
}
else if(text[i] == 'e')
{
strtext += "\e";
}
else if(text[i] == 'x')
{
if(i + 2 < text.Length)
{
i++;
strtext += Net.Http.UrlPathDecode($"%{text[i]}{text[i+1]}");
i++;
}
}
else {
strtext += text[i];
}
}
}
else
{
strtext += text[i];
}
}
tokens.Add({
type = "$string",
value = strtext
});
}
break;
case ' ':
case '\n':
case '\r':
case '\t':
flush();
break;
default:
builder += text[i];
break;
}
}
flush();
var off = 0;
func parse()
{
if(tokens[off].type == "'")
{
off++;
return ["quote",parse()];
}
if(tokens[off].type == "(")
{
off++;
var ls = [];
while(tokens[off].type != ")")
{
ls.Add(parse());
}
off++;
return ls;
}
if(tokens[off].type == "ident")
{
return tokens[off++].value;
}
if(tokens[off].type == "$string")
{
return ["$string",tokens[off++].value];
}
return [];
}
const ls = [];
while(off < tokens.Length)
ls.Add(parse());
return ls;
}
//Console.WriteLine(CrossLisp.toCrossLangText(parseLisp("")));