This commit is contained in:
2025-05-08 21:27:29 -05:00
parent c143b8d3a5
commit 7456bf9bc0
49 changed files with 604 additions and 1197 deletions

1
.gitignore vendored
View File

@@ -2,4 +2,5 @@ bin
bin-tmp bin-tmp
obj obj
shell_archive shell_archive
tmp
*.crvm *.crvm

View File

@@ -8,16 +8,10 @@
"homepage": "https://crosslang.tesseslanguage.com/", "homepage": "https://crosslang.tesseslanguage.com/",
"license": "MIT", "license": "MIT",
"template_name": "emptyweb", "template_name": "emptyweb",
"description": "An empty website with my template engine", "description": "An empty website",
"template_info": { "template_info": {
"type": "console" "type": "console"
}, },
"template_project_dependencies": [
{
"name": "Tesses.CrossLang.Markup",
"version": "1.0.0.0-prod"
}
],
"template_extra_text_ftles": [], "template_extra_text_ftles": [],
"template_ignored_files": ["bin","obj"] "template_ignored_files": ["bin","obj"]
} }

View File

@@ -1,8 +1,7 @@
<?page() route="/" ?> <?page() route="/" ?>
<?Shell?> <?Shell?>
<?arg_component() ?> <?arg_component() ?>
<h1>Hello, world</h1>
<span>Views: <?expr ++count ?></span>
<?end?> <?end?>
<?end?> <?end?>
<?end?> <?end?>

View File

@@ -0,0 +1,14 @@
func Components.Shell(body)
{
return <!DOCTYPE html>
<html lang={"en"}>
<head>
<meta charset={"UTF-8"}>
<meta name={"viewport"} content={"width=device-width, initial-scale=1.0"}>
<title>Hello, world</title>
</head>
<body>
<raw(body)>
</body>
</html>;
}

View File

@@ -0,0 +1,9 @@
var count = 0;
func Pages.Index()
{
return Components.Shell(
<h1>Hello, world</h1>
<span>Views: {++count}</span>
);
}

View File

@@ -1,5 +1,12 @@
var count = 0;
func main(args) func main(args)
{ {
Net.Http.ListenSimpleWithLoop(Router,4206); Net.Http.ListenSimpleWithLoop((ctx)=>{
if(ctx.Path == "/")
{
ctx.WithMimeType("text/html").SendText(Pages.Index());
return true;
}
return false;
},4206);
} }

View File

@@ -12,13 +12,6 @@
"template_info": { "template_info": {
"type": "console" "type": "console"
}, },
"template_project_dependencies": [
{
"name": "Tesses.CrossLang.Markup",
"version": "1.0.0.0-prod"
}
],
"template_extra_text_ftles": ["/components/shell.tcrml"],
"template_ignored_files": ["bin","obj"] "template_ignored_files": ["bin","obj"]
} }
} }

View File

@@ -0,0 +1,5 @@
var count = 0;
func Components.Counter()
{
return <p>Count is {++count}</p>;
}

View File

@@ -1,17 +1,16 @@
<?resource name="simple.min.css" route="/css/simple.min.css" ?> func Components.Shell(title,pages,body)
<?resource name="favicon.ico" route="/favicon.ico" ?> {
<?component(title,pages,body) name="Shell" ?> return <!DOCTYPE html>
<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CrossLang - <?expr Net.Http.HtmlEncode(title) ?></title> <title>%PROJECT_NAME% - {title}</title>
<link rel="stylesheet" href="./css/simple.min.css"> <link rel="stylesheet" href="./css/simple.min.css">
</head> </head>
<body> <body>
<header> <header>
<h1>CrossLang</h1> <h1>%PROJECT_NAME%</h1>
<nav> <nav>
<ul> <ul>
<?code <?code
@@ -32,5 +31,5 @@
<p>Created using <a href="https://crosslang.tesseslanguage.com/">CrossLang</a> and <a href="https://simplecss.org/">SimpleCSS</a></p> <p>Created using <a href="https://crosslang.tesseslanguage.com/">CrossLang</a> and <a href="https://simplecss.org/">SimpleCSS</a></p>
</footer> </footer>
</body> </body>
</html> </html>;
<?end?> }

View File

@@ -1,5 +1,21 @@
var count = 0; var count = 0;
func main(args) func main(args)
{ {
Net.Http.ListenSimpleWithLoop(Router,4206); Net.Http.ListenSimpleWithLoop((ctx)=>{
if(ctx.Path == "/")
{
ctx.WithMimeType("text/html").SendText(Pages.Index());
return true;
}
else if(ctx.Path == "/simple.min.css")
{
ctx.WithMimeType("text/css").SendBytes(embed("simple.min.css"));
return true;
}
else if(ctx.Path == "/favicon.ico")
{
ctx.WithMimeType("image/x-icon").SendBytes(embed("favicon.ico"));
return true;
}
},4206);
} }

View File

@@ -31,20 +31,7 @@ func Tesses.CrossLang.PackageManager()
var configRoot = Env.CrossLangConfig; var configRoot = Env.CrossLangConfig;
var packageCache = configRoot / "PackageCache"; var packageCache = configRoot / "PackageCache";
FS.Local.CreateDirectory(packageCache); FS.Local.CreateDirectory(packageCache);
func FileReadByteArray(fs,path)
{
var f = fs.OpenFile(path,"rb");
var ms = FS.MemoryStream(true);
f.CopyTo(ms);
var buff = ms.GetBytes();
f.Close();
return buff;
}
func FileReadString (fs,path) {
var buff = FileReadByteArray(fs,path).ToString();
ms.Close();
return text;
}
return { return {
Offline = false, Offline = false,
ParseFileName, ParseFileName,
@@ -65,7 +52,7 @@ func Tesses.CrossLang.PackageManager()
var pkgFile = packageCache / name / v.ToString(); var pkgFile = packageCache / name / v.ToString();
if(useCache && FS.Local.RegularFileExists(pkgFile)) if(useCache && FS.Local.RegularFileExists(pkgFile))
{ {
return FileReadByteArray(FS.Local,pkgFile); return FS.ReadAllBytes(FS.Local,pkgFile);
} }
if(this.Offline) return null; if(this.Offline) return null;
@@ -77,7 +64,7 @@ func Tesses.CrossLang.PackageManager()
var req = Net.Http.MakeRequest(uri); var req = Net.Http.MakeRequest(uri);
if(req.StatusCode == 200) if(req.StatusCode == 200)
{ {
var strm = FS.MemoryStream(true); var strm = new MemoryStream(true);
req.CopyToStream(strm); req.CopyToStream(strm);
if(useCache) { if(useCache) {

View File

@@ -94,7 +94,7 @@ func Tesses.CrossLang.BuildTool(pm)
if(TypeOf(info.type) == "String" && info.type == "template") if(TypeOf(info.type) == "String" && info.type == "template")
{ {
//vfs, strm, name, version, info //vfs, strm, name, version, info
var subdir = FS.SubdirFilesystem(FS.Local,dir); var subdir = new SubdirFilesystem(FS.Local,dir);
var output = $"{name}-{version}.crvm"; var output = $"{name}-{version}.crvm";
var outFile = FS.Local.OpenFile(dir / outputDir / output,"wb"); var outFile = FS.Local.OpenFile(dir / outputDir / output,"wb");
@@ -166,7 +166,7 @@ func Tesses.CrossLang.BuildTool(pm)
env.LoadFileWithDependencies(FS.Local,newFile); env.LoadFileWithDependencies(FS.Local,newFile);
env.GetDictionary().RunTool({ env.GetDictionary().RunTool({
Project = FS.SubdirFilesystem(FS.Local, dir), Project = new SubdirFilesystem(FS.Local, dir),
ProjectInfo = info, ProjectInfo = info,
GeneratedSource = sources, GeneratedSource = sources,
Config = this.Config Config = this.Config
@@ -236,7 +236,7 @@ func Tesses.CrossLang.BuildTool(pm)
Info = Json.Encode(info), Info = Json.Encode(info),
Icon = icon, Icon = icon,
Tools = file_tools, Tools = file_tools,
ResourceFileSystem = FS.SubdirFilesystem(FS.Local, dir / resDir), ResourceFileSystem = new SubdirFilesystem(FS.Local, dir / resDir),
Dependencies = file_deps, Dependencies = file_deps,
Output = outFile Output = outFile
}); });

View File

@@ -1,3 +0,0 @@
<?component() name="Counter" ?>
<p>Count is <?expr count++ ?></p>
<?end?>

View File

@@ -1,36 +0,0 @@
<?resource name="simple.min.css" route="/css/simple.min.css" ?>
<?resource name="favicon.ico" route="/favicon.ico" ?>
<?component(title,pages,body) name="Shell" ?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Greater Website - <?expr Net.Http.HtmlEncode(title) ?></title>
<link rel="stylesheet" href="./css/simple.min.css">
</head>
<body>
<header>
<h1>My Greater Website</h1>
<nav>
<ul>
<?code
each(var item : pages)
{
?>
<li><a <?code if(item.active) { ?> aria-current="page" <?code } ?> href="<?expr Net.Http.UrlPathEncode(item.route) ?>"><?expr Net.Http.HtmlEncode(item.text) ?></a></li>
<?code
}
?>
</ul>
</nav>
</header>
<h1><?expr Net.Http.HtmlEncode(title) ?></h1>
<?body?>
<?end?>
<footer>
<p>Created using <a href="https://crosslang.tesseslanguage.com/">CrossLang</a> and <a href="https://simplecss.org/">SimpleCSS</a></p>
</footer>
</body>
</html>
<?end?>

View File

@@ -1,10 +0,0 @@
{
"name": "Tesses.CrossLang.ExampleSite",
"version": "1.0.0.0-prod",
"project_dependencies": [
"../Tesses.CrossLang.Markup"
],
"info": {
"type": "console"
}
}

View File

@@ -1,28 +0,0 @@
<?page() route="/about" ?>
<?code
var pages = [
{
active = false,
route = "/",
text = "Home"
},
{
active = false,
route = "/counter",
text = "Counter"
},
{
active = true,
route = "/about",
text = "About"
}
];
?>
<?Shell?>
<?arg "About Me" ?>
<?arg pages ?>
<?arg_component() ?>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Laboriosam possimus nisi ab nobis magni, error minus vero neque iusto beatae, quasi nostrum. Ut repudiandae expedita reprehenderit tenetur. Sunt, adipisci cumque!</p>
<?end?>
<?end?>
<?end?>

View File

@@ -1,29 +0,0 @@
<?page() route="/counter" ?>
<?code
var pages = [
{
active = false,
route = "/",
text = "Home"
},
{
active = true,
route = "/counter",
text = "Counter"
},
{
active = false,
route = "/about",
text = "About"
}
];
?>
<?Shell?>
<?arg "Counter" ?>
<?arg pages ?>
<?arg_component() ?>
<?Counter ?>
<?end?>
<?end?>
<?end?>
<?end?>

View File

@@ -1,28 +0,0 @@
<?page() route="/" ?>
<?code
var pages = [
{
active = true,
route = "/",
text = "Home"
},
{
active = false,
route = "/counter",
text = "Counter"
},
{
active = false,
route = "/about",
text = "About"
}
];
?>
<?Shell?>
<?arg "Main Page" ?>
<?arg pages ?>
<?arg_component() ?>
<p>1 John 4:4: You, dear children, are from God and have overcome them, because the one who is in you is greater than the one who is in the world.</p>
<?end?>
<?end?>
<?end?>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +0,0 @@
var count = 0;
func main(args)
{
Net.Http.ListenSimpleWithLoop(Router,4206);
}

View File

@@ -1,11 +0,0 @@
{
"name": "Tesses.CrossLang.Markup",
"version": "1.0.0.0-prod",
"info": {
"maintainer": "Mike Nolan",
"type": "compile_tool",
"repo": "https://onedev.site.tesses.net/CrossLang/CrossLangExtras",
"homepage": "https://crosslang.tesseslanguage.com/",
"license": "LGPLv3"
}
}

View File

@@ -1,858 +0,0 @@
func crossmarkuplexer(data)
{
var tokens = [];
var i = 0;
var peeked=null;
var inSpecial=false;
var builder = "";
func read()
{
if(peeked)
{
var myPeeked=peeked;
peeked = null;
return myPeeked;
}
if(i < data.Length) {
var rc = data[i++];
return rc;
}
return null;
}
func peek()
{
if(peeked) return peeked;
peeked = read();
return peeked;
}
func flush()
{
if(builder.Count > 0)
{
tokens.Add({
Type = inSpecial ? "Identifier" : "Text",
Text = builder
});
builder = "";
}
}
func ReadChar()
{
var r2 = read();
if(!r2) return null;
if(r2 == '\\')
{
r2 = read();
if(!r2)
{
return null;
}
return $"\\{r2}";
}
return r2.ToString();
}
func ReadString()
{
var str = "";
while(var myChar = ReadChar())
{
if(myChar == "\"") break;
str += myChar;
}
return str;
}
while(r = read())
{
var p = peek();
if(!inSpecial && r == '<')
{
if(p == '?')
{
read();
flush();
tokens.Add({
Type = "EnterSpecial"
});
inSpecial=true;
}
else
{
builder += "<";
}
}
else if(inSpecial && (r == '\r' || r == '\n' || r == ' ' || r == '\t'))
{
flush();
}
else if(inSpecial && r == '\"')
{
flush();
var myStr = ReadString();
tokens.Add({
Type = "String",
Text = myStr
});
}
else if(inSpecial && r == '\'')
{
flush();
var myChr = ReadChar();
tokens.Add({
Type = "Char",
Text = myChr
});
read();
}
else if(inSpecial && r == '=')
{
flush();
tokens.Add({
Type = "Equals"
});
}
else if(inSpecial && r == '(')
{
flush();
tokens.Add({
Type = "OpenParen"
});
}
else if(inSpecial && r == ')')
{
flush();
tokens.Add({
Type = "CloseParen"
});
}
else if(inSpecial && r == ',')
{
flush();
tokens.Add({
Type = "Comma"
});
}
else if(inSpecial && r == '?')
{
if(p == '?')
{
read();
builder += "?";
}
else if(p == '>')
{
read();
flush();
tokens.Add({
Type = "ExitSpecial"
});
inSpecial=false;
}
else
{
builder += read().ToString();
}
}
else
{
builder += r.ToString();
}
}
flush();
return tokens;
}
func crossmarkupparser(tokens)
{
var i = 0;
func NotEnd()
{
if(i + 3 > tokens.Count) return false;
if(tokens[i].Type != "EnterSpecial")
return true;
if(tokens[i+1].Type != "Identifier")
return true;
if(tokens[i+1].Text != "end")
return true;
if(tokens[i+2].Type != "ExitSpecial")
return true;
return false;
}
func EnsureEnd()
{
if(NotEnd())
{
throw "Must end with <?end?>";
}
i += 3;
}
func TokenTypeIs(type)
{
return i < tokens.Length && tokens[i].Type == type;
}
func EnsureTokenType(type)
{
if(!TokenTypeIs(type))
{
throw $"The token is {type} which is not {tokens[i].Type}";
}
i++;
}
func ConsumeIfTokenTypeIs(type)
{
if(TokenTypeIs(type)) i++;
}
func parse_node()
{
if(i < tokens.Length)
{
var myToken = tokens[i++];
if(myToken.Type == "EnterSpecial")
{
if(i < tokens.Length)
{
var myToken2 = tokens[i++];
if(myToken2.Type == "Identifier")
{
if(myToken2.Text == "page")
{
var pageargs = [];
var nodes =[];
var route = "/";
var router_function = "Router";
//its a page
EnsureTokenType("OpenParen");
while(!TokenTypeIs("CloseParen"))
{
ConsumeIfTokenTypeIs("Comma");
if(i < tokens.Length && tokens[i].Type == "Identifier")
{
pageargs.Add(tokens[i].Text);
i++;
}
}
EnsureTokenType("CloseParen");
while(!TokenTypeIs("ExitSpecial"))
{
if(TokenTypeIs("Identifier"))
{
var key = tokens[i++].Text;
EnsureTokenType("Equals");
if(TokenTypeIs("String"))
{
var value = tokens[i++].Text;
if(key == "route")
route = value;
else if(key == "router_function")
router_function = value;
else
throw $"Unknown property {key}";
}
else
{
throw "Not a string";
}
}
else
{
throw "Not an identifier";
}
}
EnsureTokenType("ExitSpecial");
Console.WriteLine($"Creating page: {route}");
while(NotEnd())
{
nodes.Add(parse_node());
}
EnsureEnd();
return {
Type = "PageNode",
Arguments = pageargs,
Route = route,
RouterFunction = router_function,
Nodes = nodes
};
}
else if(myToken2.Text == "component")
{
var pageargs = [];
var nodes =[];
var name = "Component";
//its a component
EnsureTokenType("OpenParen");
while(!TokenTypeIs("CloseParen"))
{
ConsumeIfTokenTypeIs("Comma");
if(i < tokens.Length && tokens[i].Type == "Identifier")
{
pageargs.Add(tokens[i].Text);
i++;
}
}
EnsureTokenType("CloseParen");
while(!TokenTypeIs("ExitSpecial"))
{
if(TokenTypeIs("Identifier"))
{
var key = tokens[i++].Text;
EnsureTokenType("Equals");
if(TokenTypeIs("String"))
{
var value = tokens[i++].Text;
if(key == "name")
name = value;
else
throw $"Unknown property {key}";
}
else
{
throw "Not a string";
}
}
else
{
throw "Not an identifier";
}
}
Console.WriteLine($"Creating component: {name}");
EnsureTokenType("ExitSpecial");
while(NotEnd())
{
nodes.Add(parse_node());
}
EnsureEnd();
return {
Type = "ComponentNode",
Arguments = pageargs,
Name = name,
Nodes = nodes
};
}
else if(myToken2.Text == "code")
{
var nodes = [];
while(!TokenTypeIs("ExitSpecial"))
{
if(i < tokens.Length)
nodes.Add(parse_node());
}
EnsureTokenType("ExitSpecial");
return {
Type = "CodeNode",
Nodes = nodes
};
}
else if(myToken2.Text == "resource")
{
var name = "";
var route = "";
var router_function = "Router";
while(!TokenTypeIs("ExitSpecial"))
{
if(TokenTypeIs("Identifier"))
{
var key = tokens[i++].Text;
EnsureTokenType("Equals");
if(TokenTypeIs("String"))
{
var value = tokens[i++].Text;
if(key == "name")
name = value;
else if(key == "route")
route = value;
else if(key == "router_function")
router_function = value;
else
throw $"Unknown property {key}";
}
else
{
throw "Not a string";
}
}
else
{
throw "Not an identifier";
}
}
EnsureTokenType("ExitSpecial");
return {
Type = "EmbedNode",
Name = name,
Route = route,
RouterFunction = router_function
};
}
else if(myToken2.Text == "expr")
{
var nodes = [];
while(!TokenTypeIs("ExitSpecial"))
{
if(i < tokens.Length)
nodes.Add(parse_node());
}
EnsureTokenType("ExitSpecial");
return {
Type = "ExprNode",
Nodes = nodes
};
}
else
{
EnsureTokenType("ExitSpecial");
var args = [];
while(NotEnd())
{
if(TokenTypeIs("Text"))
{
EnsureTokenType("Text");
}
else if(TokenTypeIs("EnterSpecial"))
{
EnsureTokenType("EnterSpecial");
var myToken3 = tokens[i++];
if(myToken3.Type == "Identifier")
{
if(myToken3.Text == "arg")
{
var nodes = [];
while(!TokenTypeIs("ExitSpecial"))
{
if(i < tokens.Length)
nodes.Add(parse_node());
}
EnsureTokenType("ExitSpecial");
args.Add({
Type = "ArgNode",
Nodes = nodes
});
}
else if(myToken3.Text == "arg_component")
{
var pageargs = [];
var nodes =[];
//its a component
EnsureTokenType("OpenParen");
while(!TokenTypeIs("CloseParen"))
{
ConsumeIfTokenTypeIs("Comma");
if(i < tokens.Length && tokens[i].Type == "Identifier")
{
pageargs.Add(tokens[i].Text);
i++;
}
}
EnsureTokenType("CloseParen");
EnsureTokenType("ExitSpecial");
while(NotEnd())
{
nodes.Add(parse_node());
}
EnsureEnd();
args.Add({
Type = "ArgComponentNode",
Arguments = pageargs,
Nodes = nodes
});
}
}
else
{
throw "Must be an identifier";
}
}
}
EnsureEnd();
return {
Type = "UseComponentNode",
Name = myToken2.Text,
Arguments = args
};
}
}
}
}
else if(myToken.Type == "Identifier")
{
return {
Type = "IdentifierNode",
Text = myToken.Text
};
}
else if(myToken.Type == "Text")
{
return {
Type = "TextNode",
Text = myToken.Text
};
}
else if(myToken.Type == "Char")
{
return {
Type = "CharNode",
Text = $"\'{myToken.Text}\'"
};
}
else if(myToken.Type == "String")
{
return {
Type = "StringNode",
Text = $"\"{myToken.Text}\""
};
}
else if(myToken.Type == "Equals" || myToken.Type == "OpenParen" || myToken.Type == "CloseParen" || myToken.Type == "Comma" || myToken.Type == "")
{
return {
Type = $"{myToken.Type}Node"
};
}
}
return null;
}
var nodes = [];
while(i < tokens.Length)
{
nodes.Add(parse_node());
}
return {
Type = "RootNode",
Nodes = nodes
};
}
func crossmarkupgen(ast)
{
var page_functions = [];
var code = "";
func add_to_page(name, code)
{
each(var item : page_functions)
{
if(item.Key == name)
{
item.Value += code;
return null;
}
}
page_functions.Add({
Key = name,
Value = code,
Embeds = ""
});
}
func add_to_embeds(name, embeddata)
{
each(var item : page_functions)
{
if(item.Key == name)
{
if(item.Embeds.Count > 0)
{
item.Embeds += "else ";
}
item.Embeds += embeddata;
return null;
}
}
page_functions.Add({
Key = name,
Value = "",
Embeds = embeddata
});
}
func generate_node(node)
{
func myescape(txt)
{
var out = "";
each(var c : txt)
{
var cI = c.ToLong();
if(cI < 32 || cI > 126)
{
out += $"\\x{(cI % 0xFF).ToHexString(2)}";
}
else if(c == '\"')
{
out += "\\\"";
}
else if(c == '\'')
{
out += "\\\'";
}
else if(c == '\\')
{
out += "\\\\";
}
else {
out += c;
}
}
return out;
}
if(node.Type == "PageNode")
{
var codea = $"if(ctx.Path == \"{node.Route}\")";
codea += "{__writer = ctx.OpenResponseStream(); ";
each(var a : node.Arguments)
{
codea += $"var {a} = ctx.QueryParams.TryGetFirst(\"{a}\");";
}
each(var item : node.Nodes)
{
codea += generate_node(item);
}
codea += " __writer.Close(); return true;}";
add_to_page(node.RouterFunction,codea);
return "";
}
else if(node.Type == "EmbedNode")
{
var codea = $"if(ctx.Path == \"{node.Route}\")";
codea += "{";
codea += $"ctx.WithMimeType(Net.Http.MimeType(\"{node.Name}\")).SendBytes(embed(\"{node.Name}\"));";
codea += "return true;";
codea += "}";
add_to_embeds(node.RouterFunction, codea);
}
else if(node.Type == "TextNode")
{
return $"write(\"{myescape(node.Text)}\");";
}
else if(node.Type == "ExprNode")
{
var code = "write((";
each(var item : node.Nodes)
{
code += generate_node(item);
}
code += ").ToString());";
return code;
}
else if(node.Type == "CodeNode")
{
var code = "";
each(var item : node.Nodes)
{
code += generate_node(item);
}
return code;
}
else if(node.Type == "ComponentNode")
{
var code = $"func {node.Name}(write,ctx";
each(var arg0 : node.Arguments)
{
code += $",{arg0}";
}
code += "){";
each(var n : node.Nodes)
{
code += generate_node(n);
}
code += "}";
return code;
}
else if(node.Type == "UseComponentNode")
{
var code = $"{node.Name}(write,ctx";
each(var arg : node.Arguments)
{
code += ",";
if(arg.Type == "ArgNode")
{
each(var itm : arg.Nodes)
{
code += generate_node(itm);
}
}
else if(arg.Type == "ArgComponentNode")
{
code += "(write,ctx";
each(var arg0 : arg.Arguments)
{
code += $",{arg0}";
}
code += ")=>{";
each(var n : arg.Nodes)
{
code += generate_node(n);
}
code += "}";
}
}
code += ");";
return code;
}
else if(node.Type == "CharNode")
{
return $" {node.Text} ";
}
else if(node.Type == "StringNode")
{
return $" {node.Text} ";
}
else if(node.Type == "IdentifierNode")
{
return $" {node.Text} ";
}
else if(node.Type == "OpenParenNode")
{
return " ( ";
}
else if(node.Type == "CloseParenNode")
{
return " ) ";
}
else if(node.Type == "CommaNode")
{
return " , ";
}
else if(node.Type == "EqualsNode")
{
return " = ";
}
else if(node.Type == "RootNode")
{
var code = "";
each(var item : node.Nodes)
{
if(item.Type != "TextNode")
code += generate_node(item);
}
each(var pg : page_functions)
{
code += $"func {pg.Key}(ctx)";
code += "{";
if(pg.Embeds.Count > 0)
{
code += pg.Embeds + "else{";
}
code += "ctx.WithMimeType(\"text/html\");";
code += "var __writer = null;";
code += "func write(__text){ __writer.WriteText(__text); }";
code += pg.Value;
code += "__writer.Close(); ";
if(pg.Embeds.Count > 0)
{
code += "}";
}
code += " return false;}";
}
return code;
}
return "";
}
return generate_node(ast);
}
func EnumerateFiles(cfg,path)
{
var txt = "";
if(cfg.Project.DirectoryExists(path))
each(var file : cfg.Project.EnumeratePaths(path))
{
if(cfg.Project.RegularFileExists(file))
{
Console.WriteLine($"Creating markup for: {file}");
var f = cfg.Project.OpenFile(file, "rb");
var ms = FS.MemoryStream(true);
f.CopyTo(ms);
txt += ms.GetBytes().ToString();
f.Close();
ms.Close();
}
else if(cfg.Project.DirectoryExists(file))
{
EnumerateFiles(cfg, file);
}
}
return txt;
}
func RunTool(cfg)
{
var text = "";
text += EnumerateFiles(cfg, "/components");
text += EnumerateFiles(cfg, "/pages");
var c = crossmarkuplexer(text);
Console.WriteLine("Lexed");
var r = crossmarkupparser(c);
Console.WriteLine("Parsed");
var src = crossmarkupgen(r);
Console.WriteLine("Gened");
cfg.GeneratedSource.Add({Source = src, FileName="markup.tcross"});
}

View File

@@ -3,15 +3,48 @@ func DB.Open()
var path = DB.working / "data.db"; var path = DB.working / "data.db";
return Sqlite.Open(path); return Sqlite.Open(path);
} }
func DB.ChangeMotto(userId, motto)
/*func DB.GetPackageDetails(name)
{ {
DB.Lock(); DB.Lock();
var dbCon = DB.Open(); var dbCon = DB.Open();
Sqlite.Exec(dbCon,$"UPDATE accounts SET motto = {Sqlite.Escape(motto)} WHERE id = {userId};");
var account = Sqlite.Exec(dbCon,$"SELECT * FROM accounts WHERE id = {userId};");
DB.Unlock();
if(TypeOf(account) == "List" && account.Length > 0)
{
return $"/account?name={Net.Http.UrlEncode(account[0].accountName)}";
}
return "/";
}
func DB.LoginButton(ctx,active,$accountPage)
{
var session = DB.GetSession(ctx);
if(session != null)
{
DB.Lock();
var dbCon = DB.Open();
var exec = Sqlite.Exec(dbCon,$"SELECT * FROM sessions s inner join accounts a on s.accountId = a.id WHERE key = {Sqlite.Escape(session)};");
Sqlite.Close(dbCon); Sqlite.Close(dbCon);
DB.Unlock(); DB.Unlock();
}*/ var active2 = TypeOf(accountPage) == "String" ? accountPage == exec[0].accountName : false;
if(TypeOf(exec) == "List" && exec.Length > 0)
{
return {
active=active2,
route = $"/account?name={Net.Http.UrlEncode(exec[0].accountName)}",
text = exec[0].accountName
};
}
}
return {
active,
route = "/login",
text = "Login"
};
}
func DB.CanUploadPackagePrefix(userId, packageName) func DB.CanUploadPackagePrefix(userId, packageName)
{ {
@@ -404,6 +437,12 @@ func DB.GetUniqueNumber()
return unum; return unum;
} }
func DB.getPort()
{
if(TypeOf(DB.Config.Port) == "Long") return DB.Config.Port;
return 4206;
}
func DB.Init(working) func DB.Init(working)
{ {
DB.working = Path.FromString(working); DB.working = Path.FromString(working);
@@ -418,7 +457,7 @@ func DB.Init(working)
if(FS.Local.FileExists(f)) FS.Local.DeleteFile(f); if(FS.Local.FileExists(f)) FS.Local.DeleteFile(f);
} }
DB.mtx = Mutex(); DB.mtx = new Mutex();
var p = DB.working / "conf.json"; var p = DB.working / "conf.json";
if(FS.Local.FileExists(p)) if(FS.Local.FileExists(p))
DB.Config = Json.Decode(FS.ReadAllText(FS.Local, p)); DB.Config = Json.Decode(FS.ReadAllText(FS.Local, p));
@@ -430,7 +469,7 @@ func DB.Init(working)
var dbCon = DB.Open(); var dbCon = DB.Open();
Sqlite.Exec(dbCon,"CREATE TABLE IF NOT EXISTS packages (id INTEGER PRIMARY KEY AUTOINCREMENT, packageName TEXT UNIQUE, accountId INTEGER);"); Sqlite.Exec(dbCon,"CREATE TABLE IF NOT EXISTS packages (id INTEGER PRIMARY KEY AUTOINCREMENT, packageName TEXT UNIQUE, accountId INTEGER);");
Sqlite.Exec(dbCon,"CREATE TABLE IF NOT EXISTS versions (id INTEGER PRIMARY KEY AUTOINCREMENT, packageId INTEGER, version INTEGER, description TEXT, type TEXT, maintainer TEXT, homepage TEXT, repo TEXT, license TEXT, uploadTime INTEGER);"); Sqlite.Exec(dbCon,"CREATE TABLE IF NOT EXISTS versions (id INTEGER PRIMARY KEY AUTOINCREMENT, packageId INTEGER, version INTEGER, description TEXT, type TEXT, maintainer TEXT, homepage TEXT, repo TEXT, license TEXT, uploadTime INTEGER);");
Sqlite.Exec(dbCon,"CREATE TABLE IF NOT EXISTS accounts (id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT UNIQUE, accountName TEXT UNIQUE, password_hash TEXT, password_salt TEXT, motto TEXT, verifyKey TEXT UNIQUE, flags INTEGER);"); Sqlite.Exec(dbCon,"CREATE TABLE IF NOT EXISTS accounts (id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT UNIQUE, accountName TEXT UNIQUE, password_hash TEXT, password_salt TEXT, motto TEXT, verifyKey TEXT UNIQUE, verifyExpire INTEGER, flags INTEGER);");
Sqlite.Exec(dbCon,"CREATE TABLE IF NOT EXISTS sessions (id INTEGER PRIMARY KEY AUTOINCREMENT, accountId INTEGER, key STRING UNIQUE);"); Sqlite.Exec(dbCon,"CREATE TABLE IF NOT EXISTS sessions (id INTEGER PRIMARY KEY AUTOINCREMENT, accountId INTEGER, key STRING UNIQUE);");
Sqlite.Exec(dbCon,"CREATE TABLE IF NOT EXISTS reserved_prefixes (id INTEGER PRIMARY KEY AUTOINCREMENT, accountId INTEGER, prefix STRING UNIQUE);"); Sqlite.Exec(dbCon,"CREATE TABLE IF NOT EXISTS reserved_prefixes (id INTEGER PRIMARY KEY AUTOINCREMENT, accountId INTEGER, prefix STRING UNIQUE);");
Sqlite.Close(dbCon); Sqlite.Close(dbCon);
@@ -444,6 +483,33 @@ DB.FLAG_VERIFY = 0b00000100;
DB.ITTR = 35000; DB.ITTR = 35000;
func DB.GetAccountInfo(name)
{
DB.Lock();
var dbCon = DB.Open();
var exec = Sqlite.Exec(dbCon,$"SELECT * FROM accounts WHERE accountName = {Sqlite.Escape(name)};");
Sqlite.Close(dbCon);
DB.Unlock();
if(TypeOf(exec) == "List")
{
if(exec.Length == 1)
{
return exec[0];
}
else
{
return "No such user exists";
}
}
else
{
return exec;
}
}
func DB.GetAccountId(email, password) func DB.GetAccountId(email, password)
{ {
DB.Lock(); DB.Lock();

View File

@@ -21,9 +21,12 @@ func Shell(title,pages,body)
<each(var item : pages)> <each(var item : pages)>
<li class={"nav-item"}> <li class={"nav-item"}>
<if(item.active)> <if(item.active)>
<true>
<a class={"nav-link active"} aria-current={"page"} href={item.route}>{item.text}</a> <a class={"nav-link active"} aria-current={"page"} href={item.route}>{item.text}</a>
<else> </true>
<false>
<a class={"nav-link"} href={item.route}>{item.text}</a> <a class={"nav-link"} href={item.route}>{item.text}</a>
</false>
</if> </if>
</li> </li>
</each> </each>

View File

@@ -0,0 +1,119 @@
func Pages.Account(ctx)
{
var name = ctx.QueryParams.TryGetFirst("name");
if(TypeOf(name) != "String") name = "";
var active = DB.LoginButton(ctx,false,name);
var pages = [
{
active = false,
route = "/packages",
text = "Packages"
},
{
active = false,
route = "/upload",
text = "Upload"
},
active
];
var user = DB.GetAccountInfo(name);
var motto_ta = TypeOf(user.motto) == "String" ? user.motto : "";
//var motto=Net.Http.HtmlEncode(motto_ta).Replace("\r","").Replace("\n","<br>");
var motto = "";
if(!active.active)
{
var builder = "";
func flush()
{
if(builder.Length > 0)
{
if(builder.StartsWith("http://") || builder.StartsWith("https://") || builder.StartsWith("ftp://") || builder.StartsWith("ftps://") || builder.StartsWith("magnet:"))
{
motto += <a href={builder}>{builder}</a>;
}
else if(builder.StartsWith("mailto:"))
{
motto += <a href={builder}>{builder.Substring(7)}</a>;
}
else if(builder.StartsWith("tel:"))
{
motto += <a href={builder}>{builder.Substring(4)}</a>;
}
else
{
motto += Net.Http.HtmlEncode(builder);
}
builder="";
}
}
each(var item : motto_ta)
{
switch(item)
{
case ' ':
flush();
motto += " ";
break;
case '\n':
flush();
motto += "<br>";
break;
case '\t':
flush();
motto+= "&tab;";
break;
case '\r':
flush();
break;
default:
builder += item;
break;
}
}
flush();
}
var html =
<div class="container">
<if(TypeOf(user) == "Dictionary")>
<true>
<h1>{user.accountName}</h1>
<a href={$"./account_packages?name={Net.Http.UrlEncode(name)}"}>Packages</a>
<if(active.active)>
<true>
<form action="./change_motto" method="POST">
<if(motto_ta.Length == 0)>
<true><textarea class="form-control" name="motto" placeholder="Type your motto and/or links here" id="floatingTextarea2" style="height: 100px"></textarea></true>
<false><textarea class="form-control" name="motto" placeholder="Type your motto and/or links here" id="floatingTextarea2" style="height: 100px">{motto_ta}</textarea></false>
</if>
<input class="btn btn-primary" type="submit" value="Save">
<input type="hidden" name="csrf" value={DB.CreateCSRF(ctx)}>
<a class="btn btn-danger" href="./logout">Logout</a>
</form>
</true>
<false>
<hr>
<p><raw(motto)></p>
</false>
</if>
</true>
<false>
<if(TypeOf(user) == "String")><true>
<div>
{user}
</div>
</true></if>
</false>
</if></div>;
return Shell($"Account {name}", pages,html);
}

View File

@@ -1,4 +1,4 @@
func Pages.CheckEmail() func Pages.CheckEmail(ctx)
{ {
var pages = [ var pages = [
{ {
@@ -11,11 +11,7 @@ func Pages.CheckEmail()
route = "/upload", route = "/upload",
text = "Upload" text = "Upload"
}, },
{ DB.LoginButton(ctx,false)
active = false,
route = "/login",
text = "Login"
}
]; ];
var html = <div class={"container"}> var html = <div class={"container"}>
<h1>Please check your email.</h1> <h1>Please check your email.</h1>

View File

@@ -1,4 +1,4 @@
func Pages.Index() func Pages.Index(ctx)
{ {
var pages = [ var pages = [
@@ -12,11 +12,7 @@ func Pages.Index()
route = "/upload", route = "/upload",
text = "Upload" text = "Upload"
}, },
{ DB.LoginButton(ctx,false)
active = false,
route = "/login",
text = "Login"
}
]; ];
var html = <article><h1 class={"display-5"} style={"text-align: center;"}>Make crosslang development faster and more convenient with CPKG</h1><form action={"./packages"} method={"get"}><div class={"container text-center"}><div class={"row"}><div class={"col"}> var html = <article><h1 class={"display-5"} style={"text-align: center;"}>Make crosslang development faster and more convenient with CPKG</h1><form action={"./packages"} method={"get"}><div class={"container text-center"}><div class={"row"}><div class={"col"}>

View File

@@ -1,4 +1,4 @@
func Pages.Login() func Pages.Login(ctx)
{ {
var pages = [ var pages = [
{ {
@@ -11,11 +11,7 @@ func Pages.Login()
route = "/upload", route = "/upload",
text = "Upload" text = "Upload"
}, },
{ DB.LoginButton(ctx,true)
active = true,
route = "/login",
text = "Login"
}
]; ];
var html = <div class={"container min-vh-100 d-flex justify-content-center align-items-center"}> var html = <div class={"container min-vh-100 d-flex justify-content-center align-items-center"}>
<form action={"./login"} method={"post"} enctype={"application/x-www-form-urlencoded"}> <form action={"./login"} method={"post"} enctype={"application/x-www-form-urlencoded"}>

View File

@@ -1,4 +1,4 @@
func Pages.Package(name) func Pages.Package(ctx,name)
{ {
var package = DB.GetPackageVersions(name); var package = DB.GetPackageVersions(name);
@@ -13,16 +13,12 @@ func Pages.Package(name)
route = "/upload", route = "/upload",
text = "Upload" text = "Upload"
}, },
{ DB.LoginButton(ctx,false)
active = false,
route = "/login",
text = "Login"
}
]; ];
var html = <if(package.Length > 0)><section class={"container"}> var html = <if(package.Length > 0)><true><section class={"container"}>
<br> <br>
<img width={"64"} height={"64"} src={$"./api/v1/package_icon.png?name={Net.Http.UrlEncode(name)}&version={Net.Http.UrlEncode(package[0].version)}"} alt={"icon"}> <img width={"64"} height={"64"} src={$"./api/v1/package_icon.png?name={Net.Http.UrlEncode(name)}&version={Net.Http.UrlEncode(package[0].version)}"} alt={"icon"}>
<h1>{name}</h1> <h1>{name}</h1>
@@ -42,7 +38,9 @@ func Pages.Package(name)
<div class={"card-body"}> <div class={"card-body"}>
<if(package[0].type == "lib" || package[0].type == "compile_tool")> <if(package[0].type == "lib" || package[0].type == "compile_tool")>
<true>
crosslang add-dependency {name} crosslang add-dependency {name}
</true>
</if> </if>
</div> </div>
</div> </div>
@@ -60,16 +58,24 @@ func Pages.Package(name)
<ul> <ul>
<li>Account: <a href={$"./account?name={Net.Http.UrlEncode(package[0].accountName)}"}>{package[0].accountName}</a></li> <li>Account: <a href={$"./account?name={Net.Http.UrlEncode(package[0].accountName)}"}>{package[0].accountName}</a></li>
<if(package[0].maintainer.Length > 0)> <if(package[0].maintainer.Length > 0)>
<true>
<li>Maintainer: {package[0].maintainer}</li> <li>Maintainer: {package[0].maintainer}</li>
</true>
</if> </if>
<if(package[0].license.Length > 0)> <if(package[0].license.Length > 0)>
<true>
<li>License: {package[0].license}</li> <li>License: {package[0].license}</li>
</true>
</if> </if>
<if(package[0].homepage.Length > 0)> <if(package[0].homepage.Length > 0)>
<true>
<li>Homepage: <a href={package[0].homepage}>{package[0].homepage}</a></li> <li>Homepage: <a href={package[0].homepage}>{package[0].homepage}</a></li>
</true>
</if> </if>
<if(package[0].repo.Length > 0)> <if(package[0].repo.Length > 0)>
<true>
<li>Repo: <a href={package[0].repo}>{package[0].repo}</a></li> <li>Repo: <a href={package[0].repo}>{package[0].repo}</a></li>
</true>
</if> </if>
<li>Last updated: {package[0].uploadDate}</li> <li>Last updated: {package[0].uploadDate}</li>
<li>Latest version: {package[0].version}</li> <li>Latest version: {package[0].version}</li>
@@ -77,6 +83,7 @@ func Pages.Package(name)
<li><a href={package[0].download}>Download</a></li> <li><a href={package[0].download}>Download</a></li>
</ul> </ul>
<if(package.Length > 1)> <if(package.Length > 1)>
<true>
<br> <br>
<h3>Older versions</h3> <h3>Older versions</h3>
@@ -92,16 +99,24 @@ func Pages.Package(name)
<div class={"accordion-body"}> <div class={"accordion-body"}>
<ul> <ul>
<if(package[i].maintainer.Length > 0)> <if(package[i].maintainer.Length > 0)>
<true>
<li>Maintainer: {package[i].maintainer}</li> <li>Maintainer: {package[i].maintainer}</li>
</true>
</if> </if>
<if(package[i].license.Length > 0)> <if(package[i].license.Length > 0)>
<true>
<li>License: {package[i].license}</li> <li>License: {package[i].license}</li>
</true>
</if> </if>
<if(package[i].homepage.Length > 0)> <if(package[i].homepage.Length > 0)>
<true>
<li>Homepage: <a href={package[i].homepage}>{package[i].homepage}</a></li> <li>Homepage: <a href={package[i].homepage}>{package[i].homepage}</a></li>
</true>
</if> </if>
<if(package[i].repo.Length > 0)> <if(package[i].repo.Length > 0)>
<true>
<li>Repo: <a href={package[i].repo}>{package[i].repo}</a></li> <li>Repo: <a href={package[i].repo}>{package[i].repo}</a></li>
</true>
</if> </if>
<li>Uploaded: {package[i].uploadDate}</li> <li>Uploaded: {package[i].uploadDate}</li>
<li>Type: {package[i].type}</li> <li>Type: {package[i].type}</li>
@@ -113,8 +128,9 @@ func Pages.Package(name)
</for> </for>
</div> </div>
</true>
</if> </if>
</section> </section></true>
</if>; </if>;
return Shell($"Package {name}", pages,html); return Shell($"Package {name}", pages,html);
} }

View File

@@ -13,11 +13,7 @@ func Pages.Packages(ctx)
route = "/upload", route = "/upload",
text = "Upload" text = "Upload"
}, },
{ DB.LoginButton(ctx,false)
active = false,
route = "/login",
text = "Login"
}
]; ];
var html = <article><form action={"./packages"} method={"get"}><div class={"container text-center"}><div class={"row"}><div class={"col"}> var html = <article><form action={"./packages"} method={"get"}><div class={"container text-center"}><div class={"row"}><div class={"col"}>

View File

@@ -1,4 +1,4 @@
func Pages.Signup() func Pages.Signup(ctx)
{ {
var pages = [ var pages = [
{ {
@@ -11,11 +11,7 @@ func Pages.Signup()
route = "/upload", route = "/upload",
text = "Upload" text = "Upload"
}, },
{ DB.LoginButton(ctx,false)
active = false,
route = "/login",
text = "Login"
}
]; ];
var html = <div class={"container min-vh-100 d-flex justify-content-center align-items-center"}> var html = <div class={"container min-vh-100 d-flex justify-content-center align-items-center"}>
<form action={"./signup"} method={"post"} enctype={"application/x-www-form-urlencoded"}> <form action={"./signup"} method={"post"} enctype={"application/x-www-form-urlencoded"}>

View File

@@ -11,12 +11,9 @@ func Pages.Upload(ctx)
route = "/upload", route = "/upload",
text = "Upload" text = "Upload"
}, },
{ DB.LoginButton(ctx,false)
active = false,
route = "/login",
text = "Login"
}
]; ];
var html = <div class={"container min-vh-100 d-flex justify-content-center align-items-center"}> var html = <div class={"container min-vh-100 d-flex justify-content-center align-items-center"}>
<form action={"./upload"} method={"post"} enctype={"multipart/form-data"}> <form action={"./upload"} method={"post"} enctype={"multipart/form-data"}>
<h1>Upload Package</h1> <h1>Upload Package</h1>

View File

@@ -36,7 +36,7 @@ func main(args)
{ {
var name = ctx.QueryParams.TryGetFirst("name"); var name = ctx.QueryParams.TryGetFirst("name");
if(TypeOf(name) != "String") name = ""; if(TypeOf(name) != "String") name = "";
ctx.WithMimeType("text/html").SendText(Pages.Package(name)); ctx.WithMimeType("text/html").SendText(Pages.Package(ctx,name));
return true; return true;
} }
if(ctx.Path == "/packages") if(ctx.Path == "/packages")
@@ -78,6 +78,34 @@ func main(args)
return true; return true;
} }
} }
if(ctx.Path == "/change_motto")
{
if(ctx.Method == "POST")
{
var motto = ctx.QueryParams.TryGetFirst("motto");
if(motto == null) motto = "";
var session = DB.GetSession(ctx);
if(session == null)
{
ctx.StatusCode = 401;
ctx.SendText("<h1>You are not logged in</h1>");
return true;
}
var csrf = ctx.QueryParams.TryGetFirst("csrf");
var result = { Success=false, Reason = "Invalid CSRF"};
if(DB.VerifyCSRF(session,csrf))
{
var userId = DB.GetUserIdFromSession(session);
var url = DB.ChangeMotto(userId,motto);
ctx.StatusCode = 302;
ctx.ResponseHeaders.SetValue("Location", url);
ctx.WriteHeaders();
return true;
}
}
}
if(ctx.Path == "/upload") if(ctx.Path == "/upload")
{ {
if(ctx.Method == "GET") if(ctx.Method == "GET")
@@ -96,13 +124,13 @@ func main(args)
if(name == "package") if(name == "package")
{ {
if(hasFile) return FS.MemoryStream(true); if(hasFile) return new MemoryStream(true);
hasFile=true; hasFile=true;
return strm; return strm;
} }
else else
return FS.MemoryStream(true); return new MemoryStream(true);
}); });
strm.Close(); strm.Close();
@@ -110,6 +138,9 @@ func main(args)
var session = DB.GetSession(ctx); var session = DB.GetSession(ctx);
if(session == null) if(session == null)
{ {
if(FS.Local.FileExists(filePath))
FS.Local.DeleteFile(filePath);
ctx.StatusCode = 401; ctx.StatusCode = 401;
ctx.SendText("<h1>You are not logged in</h1>"); ctx.SendText("<h1>You are not logged in</h1>");
return true; return true;
@@ -179,7 +210,7 @@ func main(args)
{ {
if(ctx.Method == "GET") if(ctx.Method == "GET")
{ {
ctx.WithMimeType("text/html").SendText(Pages.Login()); ctx.WithMimeType("text/html").SendText(Pages.Login(ctx));
return true; return true;
} }
else if(ctx.Method == "POST") else if(ctx.Method == "POST")
@@ -219,7 +250,7 @@ func main(args)
{ {
if(ctx.Method == "GET") if(ctx.Method == "GET")
{ {
ctx.WithMimeType("text/html").SendText(Pages.Signup()); ctx.WithMimeType("text/html").SendText(Pages.Signup(ctx));
return true; return true;
} }
else if(ctx.Method == "POST") else if(ctx.Method == "POST")
@@ -275,6 +306,11 @@ func main(args)
return true; return true;
} }
} }
if(ctx.Path == "/account")
{
ctx.WithMimeType("text/html").SendText(Pages.Account(ctx));
return true;
}
if(ctx.Path == "/css/bootstrap.min.css") if(ctx.Path == "/css/bootstrap.min.css")
{ {
ctx.WithMimeType("text/css").SendBytes(embed("css/bootstrap.min.css")); ctx.WithMimeType("text/css").SendBytes(embed("css/bootstrap.min.css"));
@@ -304,9 +340,10 @@ func main(args)
} }
if(ctx.Path == "/") if(ctx.Path == "/")
{ {
ctx.WithMimeType("text/html").SendText(Pages.Index()); ctx.WithMimeType("text/html").SendText(Pages.Index(ctx));
return true; return true;
} }
return false; return false;
},4206); },DB.Port);
} }

View File

@@ -130,6 +130,203 @@ func main(args)
} }
return env.GetDictionary().main(myArgs); return env.GetDictionary().main(myArgs);
} }
else if(commandName == "debug")
{
var offline=false;
var buildPath = ".";
var nobuild=false;
var output="";
each(var flag : dd.Flags)
{
if(flag == "offline")
{
offline = true;
}
else if(flag == "help")
{
Console.WriteLine("USAGE: crosslang run [run-flags-and-options] program-arguments...");
Console.WriteLine("USAGE: crosslang run [run-flags-and-options] -- program-arguments-and-options...");
Console.WriteLine("FLAGS:");
Console.WriteLine("offline: build with no internet (don't fetch files)");
Console.WriteLine("help: this help");
Console.WriteLine("nobuild: don't build, just run");
Console.WriteLine();
Console.WriteLine("OPTIONS:");
Console.WriteLine("conf=CONFIGSTRING: specify a conf string for compile_tool(s), is the property Config");
return 0;
}
else if(flag == "nobuild")
{
nobuild=true;
}
}
var conf = "";
each(var option : dd.Options)
{
if(option.Key == "conf")
{
conf = option.Value;
}
}
if(nobuild)
{
if(FS.Local.FileExists("config.json"))
{
var proj = Json.Decode(FS.ReadAllText(FS.Local, "config.json"));
var nameVer = $"{proj.name}-{proj.version}.crvm";
var buildDir = TypeOf(proj.bin_directory) == "String" ? proj.bin_directory : "bin";
output = ./buildDir/nameVer;
if(!FS.Local.FileExists(output))
{
Console.WriteLine($"ERROR: file {output} does not exist.");
}
}
else
{
Console.WriteLine("ERROR: could not find project.");
return 1;
}
}
else
{
var pm = Tesses.CrossLang.PackageManager();
pm.Offline = offline;
var bt = Tesses.CrossLang.BuildTool(pm);
bt.Config = conf;
output = bt.BuildProject(buildPath).Output;
}
var env = VM.CreateEnvironment({});
env.RegisterOnError((ctx)=>{
if(ctx.IsBreakpoint)
{
Console.WriteLine($"Breakpoint {ctx.Breakpoint.Data} hit at: {ctx.Breakpoint.Filename}:{ctx.Breakpoint.Line}");
}
else if(TypeOf(ctx.Exception) == "Dictionary")
{
Console.WriteLine($"Exception at: {ctx.Exception.Filename}:{ctx.Exception.Line}");
Console.WriteLine(ctx.Exception);
}
else {
Console.WriteLine("thrown {ctx.Exception}");
}
GC.BarrierBegin();
while(true)
{
Console.Write("dbg> ");
var input = Console.ReadLine();
if(input == "continue")
{
break;
}
else if(input.StartsWith("getvar "))
{
var varName = input.Substring(7);
var val = ctx.Environment.GetVariable(varName);
Console.Write($"{TypeOf(val)} ");
if(TypeIsString(val))
Console.WriteLine(val.Escape());
else
Console.WriteLine(val);
}
else if(input.StartsWith("eval "))
{
var evalText = input.Substring(5);
ctx.Environment.Eval(evalText);
}
else if(input == "lsroot")
{
var root = ctx.Environment.GetRootEnvironment();
func printItems(r,name)
{
each(var item : Dictionary.Items(r))
{
switch(TypeOf(item.Value))
{
case "Dictionary":
printItems(item.Value,$"{name}{item.Key}.");
break;
case "String":
Console.WriteLine($"{name}{item.Key} = {item.Value.Escape()}");
break;
case "Closure":
case "ExternalMethod":
if(item.Value.documentation.Length > 0)
{
Console.WriteLine($"/^{item.Value.Documentation}^/");
}
{
Console.Write($"func {name}{item.Key}(");
var first=true;
each(var arg : item.Value.Arguments)
{
if(!first) Console.Write($", {arg}");
else
Console.Write(arg);
first=false;
}
Console.WriteLine(")");
}
break;
default:
Console.Write($"{name}{item.Key} = ");
Console.WriteLine(item.Value);
break;
}
}
}
printItems(root.GetDictionary(),"");
}
else if(input == "lsvar")
{
var curVersion = ctx.Environment;
Console.WriteLine("======================");
while(TypeOf(curVersion) != "RootEnvironment")
{
each(var item : Dictionary.Items(curVersion.GetDictionary()))
{
Console.Write($"{TypeOf(item.Value)} {item.Key} = ");
if(TypeIsString(item.Value))
Console.WriteLine(item.Value.Escape(true));
else
Console.WriteLine(item.Value);
}
curVersion = curVersion.GetParentEnvironment();
Console.WriteLine("======================");
}
}
else if(input == "help")
{
Console.WriteLine("getvar <VARNAME>: prints variable");
Console.WriteLine("eval <code>: eval code in environment");
Console.WriteLine("lsvar: get variables (not root environment)");
Console.WriteLine("lsroot: get variables on root environment");
Console.WriteLine("continue: continue executing");
}
}
GC.BarrierEnd();
return ctx.IsBreakpoint;
});
env.RegisterEverything();
env.LockRegister();
env.LoadFileWithDependencies(FS.Local,output);
var myArgs = [output];
for(var i = 1; i < dd.Arguments.Count; i++)
{
myArgs.Add(dd.Arguments[i]);
}
return env.GetDictionary().main(myArgs);
}
else if(commandName == "new") else if(commandName == "new")
{ {
func newHelp() func newHelp()
@@ -179,7 +376,7 @@ func main(args)
FS.Local.CreateDirectory(projectPath); FS.Local.CreateDirectory(projectPath);
var projectDir = FS.SubdirFilesystem(FS.Local, projectPath); var projectDir = new SubdirFilesystem(FS.Local, projectPath);
var strm = FS.Local.OpenFile(templateFile,"rb"); var strm = FS.Local.OpenFile(templateFile,"rb");

View File

@@ -0,0 +1,8 @@
{
"info": {
"type": "lib",
"description": "The standard library of crosslang"
},
"name": "Tesses.CrossLang.Std",
"version": "1.0.0.0-prod"
}

View File

@@ -0,0 +1,41 @@
/^
Create a new exception
^/
func New.Exception(message,$type,$inner)
{
if(TypeIsString(type))
{
return {
Message = message,
InnerException = inner,
Type = type,
ToString = Std.Internal.Exception.ToString
};
}
else
{
return {
Message = message,
InnerException = inner,
Type = "Exception",
ToString = Std.Internal.Exception.ToString
};
}
}
/^Out of range exception^/
func New.OutOfRangeException(varName, $inner)
{
return new Exception($"{varName} is out of range.","OutOfRangeException",inner);
}
/^Exception ToString^/
func Std.Internal.Exception.ToString(this)
{
var messagePart = $"{this.Type}: {this.Message}";
if(this.InnerException != undefined && this.InnerException != null)
{
var innerEx = this.InnerException.ToString().Replace("\n","\n\t");
return $"{messagePart}\nInner exception:\n{innerEx}";
}
return messagePart;
}

View File

@@ -1,3 +0,0 @@
<?component() name="Counter" ?>
<p>Count is <?expr count++ ?></p>
<?end?>

View File

@@ -1,8 +0,0 @@
{
"project_dependencies": ["../Tesses.CrossLang.Markup"],
"info": {
"type": "console"
},
"version": "1.0.0.0-prod",
"name": "Tesses.CrossLang.WebSite"
}

View File

@@ -1,35 +0,0 @@
<?page() route="/downloads" ?>
<?code
var pages = [
{
active = false,
route = "/",
text = "Home"
},
{
active = true,
route = "/downloads",
text = "Downloads"
}
];
?>
<?Shell?>
<?arg "Downloads" ?>
<?arg pages ?>
<?arg_component() ?>
<h2>Source Code</h2>
<ul>
<li><a href="https://onedev.site.tesses.net/crosslang">CrossLang</a></li>
<li><a href="https://onedev.site.tesses.net/crosslang/crosslangextras">CrossLang Essentials</a></li>
</ul>
<h2>Binaries</h2>
<!--<ul>
<li><a href="./downloads/windows">Windows</a></li>
<li><a href="./downloads/mac">Mac</a></li>
<li><a href="./downloads/linux">Linux</a></li>
<li><a href="./downloads/wii">Wii</a></li>
<li><a href="./downloads/iso">ISO (Burn to Disc)</a></li>
</ul>-->
<?end?>
<?end?>
<?end?>

View File

@@ -1,24 +0,0 @@
<?page() route="/" ?>
<?code
var pages = [
{
active = true,
route = "/",
text = "Home"
},
{
active = false,
route = "/downloads",
text = "Downloads"
}
];
?>
<?Shell?>
<?arg "Home" ?>
<?arg pages ?>
<?arg_component() ?>
<p>This is the website for my programming language</p>
<p>1 John 4:4: You, dear children, are from God and have overcome them, because the one who is in you is greater than the one who is in the world.</p>
<?end?>
<?end?>
<?end?>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +0,0 @@
var count = 0;
func main(args)
{
Net.Http.ListenSimpleWithLoop(Router,4206);
}

View File

@@ -26,9 +26,10 @@ func main(args)
cmd("crossvm",["./Tesses.CrossLang.BuildEssentials/bin-tmp/Tesses.CrossLang.BuildEssentials-1.0.0.0-prod.crvm","Tesses.CrossLang.Shell"]); cmd("crossvm",["./Tesses.CrossLang.BuildEssentials/bin-tmp/Tesses.CrossLang.BuildEssentials-1.0.0.0-prod.crvm","Tesses.CrossLang.Shell"]);
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Tesses.CrossLang.PackageServer"]); cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Tesses.CrossLang.PackageServer"]);
//cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Tesses.CrossLang.WebSite"]); //cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Tesses.CrossLang.WebSite"]);
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Tesses.CrossLang.Std"]);
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/console"]); cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/console"]);
// cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/emptyweb"]); cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/emptyweb"]);
// cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/web"]); cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/web"]);
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/template"]); cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/template"]);
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/lib"]); cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/lib"]);
cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/compiletool"]); cmd("crossvm",["./Tesses.CrossLang.Shell/bin/Tesses.CrossLang.Shell-1.0.0.0-prod.crvm","build","Templates/compiletool"]);

View File

@@ -13,7 +13,7 @@ func install()
{ {
var d = Env.CrossLangConfig; var d = Env.CrossLangConfig;
FS.Local.CreateDirectory(d); FS.Local.CreateDirectory(d);
var sdfs = FS.SubdirFilesystem(FS.Local, d); var sdfs = new SubdirFilesystem(FS.Local, d);
var strm = FS.Local.OpenFile(name,"rb"); var strm = FS.Local.OpenFile(name,"rb");
FS.ExtractArchive(strm, sdfs); FS.ExtractArchive(strm, sdfs);
sdfs.Close(); sdfs.Close();
@@ -23,7 +23,7 @@ func install()
func create_archive() func create_archive()
{ {
var tmpFS = FS.SubdirFilesystem(FS.Local,"crosslang_shell_archive_maker/tmp"); var tmpFS = new SubdirFilesystem(FS.Local,"crosslang_shell_archive_maker/tmp");
func copyFile(src,dest) func copyFile(src,dest)
{ {
if(!FS.Local.FileExists(src)) return; if(!FS.Local.FileExists(src)) return;
@@ -51,8 +51,8 @@ func create_archive()
copyFile("Templates/console/bin/Tesses.CrossLang.Template.Console-1.0.0.0-prod.crvm", templates / "console.crvm"); copyFile("Templates/console/bin/Tesses.CrossLang.Template.Console-1.0.0.0-prod.crvm", templates / "console.crvm");
copyFile("Templates/lib/bin/Tesses.CrossLang.Template.Library-1.0.0.0-prod.crvm", templates / "lib.crvm"); copyFile("Templates/lib/bin/Tesses.CrossLang.Template.Library-1.0.0.0-prod.crvm", templates / "lib.crvm");
copyFile("Templates/template/bin/Tesses.CrossLang.Template.Template-1.0.0.0-prod.crvm", templates / "template.crvm"); copyFile("Templates/template/bin/Tesses.CrossLang.Template.Template-1.0.0.0-prod.crvm", templates / "template.crvm");
//copyFile("Templates/web/bin/Tesses.CrossLang.Template.Website-1.0.0.0-prod.crvm", templates / "web.crvm"); copyFile("Templates/web/bin/Tesses.CrossLang.Template.Website-1.0.0.0-prod.crvm", templates / "web.crvm");
//copyFile("Templates/emptyweb/bin/Tesses.CrossLang.Template.EmptyWebsite-1.0.0.0-prod.crvm", templates / "emptyweb.crvm"); copyFile("Templates/emptyweb/bin/Tesses.CrossLang.Template.EmptyWebsite-1.0.0.0-prod.crvm", templates / "emptyweb.crvm");
copyFile("Templates/tool/bin/Tesses.CrossLang.Template.Tool-1.0.0.0-prod.crvm", templates / "tool.crvm"); copyFile("Templates/tool/bin/Tesses.CrossLang.Template.Tool-1.0.0.0-prod.crvm", templates / "tool.crvm");
var packageCache = r / "PackageCache"; var packageCache = r / "PackageCache";
@@ -60,9 +60,12 @@ func create_archive()
tmpFS.CreateDirectory(packageCache / "Tesses.CrossLang.Args"); tmpFS.CreateDirectory(packageCache / "Tesses.CrossLang.Args");
tmpFS.CreateDirectory(packageCache / "Tesses.CrossLang.BuildEssentials"); tmpFS.CreateDirectory(packageCache / "Tesses.CrossLang.BuildEssentials");
tmpFS.CreateDirectory(packageCache / "Tesses.CrossLang.Markup"); tmpFS.CreateDirectory(packageCache / "Tesses.CrossLang.Markup");
tmpFS.CreateDirectory(packageCache / "Tesses.CrossLang.Std");
copyFile("Tesses.CrossLang.Args/bin/Tesses.CrossLang.Args-1.0.0.0-prod.crvm", packageCache / "Tesses.CrossLang.Args" / "1.0.0.0-prod"); copyFile("Tesses.CrossLang.Args/bin/Tesses.CrossLang.Args-1.0.0.0-prod.crvm", packageCache / "Tesses.CrossLang.Args" / "1.0.0.0-prod");
copyFile("Tesses.CrossLang.BuildEssentials/bin/Tesses.CrossLang.BuildEssentials-1.0.0.0-prod.crvm", packageCache / "Tesses.CrossLang.BuildEssentials" / "1.0.0.0-prod"); copyFile("Tesses.CrossLang.BuildEssentials/bin/Tesses.CrossLang.BuildEssentials-1.0.0.0-prod.crvm", packageCache / "Tesses.CrossLang.BuildEssentials" / "1.0.0.0-prod");
copyFile("Tesses.CrossLang.Markup/bin/Tesses.CrossLang.Markup-1.0.0.0-prod.crvm", packageCache / "Tesses.CrossLang.Markup" / "1.0.0.0-prod"); copyFile("Tesses.CrossLang.Markup/bin/Tesses.CrossLang.Markup-1.0.0.0-prod.crvm", packageCache / "Tesses.CrossLang.Markup" / "1.0.0.0-prod");
copyFile("Tesses.CrossLang.Args/bin/Tesses.CrossLang.Args-1.0.0.0-prod.crvm", packageCache / "Tesses.CrossLang.Args" / "1.0.0.0-prod");
copyFile("Tesses.CrossLang.Std/bin/Tesses.CrossLang.Std-1.0.0.0-prod.crvm", packageCache / "Tesses.CrossLang.Std" / "1.0.0.0-prod");
var installer = FS.Local.OpenFile(name, "wb"); var installer = FS.Local.OpenFile(name, "wb");