整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

里程碑!用自己的编程语言实现了一个网站

里程碑!用自己的编程语言实现了一个网站

在上一篇终于实现了一门属于自己的编程语言 介绍了自己写的编程语言 GScript ,在文中提到希望最终可以使用 GScript 开发一个网站。

到目前为止确实是做到了,首页地址:

https://gscript.crossoverjie.top/index

要称为一个网站确实有点勉强,不过也是一个动态网页,因为返回的是 HTML,所以在当前阶段只要不嫌麻烦其实也能写一个“合格”的网站,有点像以前我们学习 Java 时的 servlet

该页面的源码地址在这里: https://github.com/crossoverjie/gscript-homepage

其实总共也就40来行代码:

class GScript{
    string author;
    string[] features;
    string since;

    GScript(string a, string[] f, string s){
        author=a;
        features=f;
        since=s;
    }
}

func (HttpContext) index(HttpContext ctx){
    string[] features={"statically", "strongly"};
    GScript gs=GScript("crossoverJie",features, "2022");
    string j=JSON(gs);
    println(j);
    string local=getCurrentTime("Asia/Shanghai","2006-01-02 15:04:05");
    println("local=" + local);
    string html=^
        <html>
            <title>GScript</title>
            <pre>
                 _     _   
 ___ ___ ___ ___|_|___| |_ 
| . |_ -|  _|  _| | . |  _|
|_  |___|___|_| |_|  _|_|  
|___|             |_|   v0.0.7   

^+ j +^
            </pre>
            <h1>current ^+ local +^</h1>
            <p><a href="https://github.com/crossoverjie/gscript-homepage">GScript-homepace source code</a></p>
        </html>
    ^;
    ctx.HTML(200, html);
}

httpHandle("GET", "/index", index);
string[] args=getOSArgs();
if (len(args)==3){
    httpRun(":" + args[2]);
}else {
    httpRun(":8000");
}

全是利用 GScript 所提供的标准库实现的,后文会详细聊聊内置 HTTP 包。

更新内容

下面重点来看看 v0.0.8 这个版本相较于上一个更新了哪些地方。

因为我是把自己当做一个开发者的角度去实现了一个 http 服务,同时还用 GScript 刷了两道简单的 LeetCode;为了让这个过程更流畅,更符合一个现代语言的使用方式,所以本次真的更新不少东西。

刷题源码:https://github.com/crossoverJie/gscript/tree/main/example/leetcode

大概如下:

  • any 类型的支持,简化标准库的实现。
  • 可以用 ^^ 来声明多行字符串,方便声明复杂字符串。
  • 更完善的类型推导,修复了上个版本中某些情况推导不出类型的bug。
  • 支持运算符重载。
  • 基本的 http 包,可以开发出 http 服务,目前能响应 JSON 以及 HTML
  • 新增内置函数:根据时区获取当前时间、获取应用启动参数等。
  • JSON 的序列表以及查询,语法级适配了 XJSON。
  • 修复了在多个 block 嵌套情况下不能正确 return 的 bug。

其实从这些更新中也能看出,上个版本只是一个简单能用的状态,而现在这个版本已经可以拿来写复杂逻辑了,当然目前还缺乏一些更友好的编译提示以及运行时错误。

下面仔细聊聊一些更新内容。

any 类型

首先是 any 通用类型,这个类似于 Java 中的 Object 和 Go 中的 interface{},极大的方便了我们编写一些标准库。

以之前内置的 hash 和 len 函数为例,需要对每种类型都实现一遍,非常麻烦而且毫无必要;现在只需要定义一次即可,代码量直接省几倍。

同理,之前实现的 Map 只支持存放 string 类型,现在便能存放任何类型的数据。

对 any 的实现过程感兴趣的朋友,今后可以单独分享一下。

运算符重载

写 go 或者是 Java 的朋友应该知道,这两门语言都无法对两个对象进行运算,编译器会直接报错。

但在一些特殊场景下还是蛮好用的,于是我参考了 C# 的语法在 GScript 中也实现了。

class Person{
 int age;
 Person(int a){
  age=a;
 }
}
Person operator + (Person p1, Person p2){
 Person pp=Person(p1.age+p2.age);
 return pp;
}
Person operator - (Person p1, Person p2){
 Person pp=Person(p1.age-p2.age);
 return pp;
}
Person p1=Person(10);
Person p2=Person(20);
Person p3=p1+p2;
println("p3.age="+p3.age);
assertEqual(p3.age, 30);

声明的函数名称必须为 operator,之后跟上运算符便实现了重载。

支持的运算符有:+-*/ < >=<=>==

JSON支持

当前版本中支持将对象、基本类型进行序列化,暂不支持反序列化为对象,但可以根据 JSON 字符串通过一定的语法查询数据。

内置了两个 JSON 相关函数:

// return JSON string
string JSON(any a){}
// JSON query with path
any JSONGet(string json, string path){}
class Person{
 int age;
 string name;
 float weight;
 bool man;
 Person(string n, int a, float w, bool m){
  name=n;
  age=a;
  weight=w;
  man=m;
 }
}
Person p1=Person("abc",10,99.99,true);
Person p2=Person("a",11,999.99,false);
string json=JSON(p1);
println(json);
// output:{"age":10,"man":true,"name":"abc","weight":99.99}

以这段代码为例,调用 JSON 函数可以将对象序列化为 JSON 字符串。


class Person{
 int age;
 string name;
 float weight;
 bool man;
 Person(string n, int a, float w, bool m){
  name=n;
  age=a;
  weight=w;
  man=m;
 }
}
Person p1=Person("abc",10,99.99,true);
string json=JSON(p1);
println(json);

int age=JSONGet(json, "age");
println(age);
assertEqual(age,10);

使用 JSONGet 函数可以在一个 JSON 字符串中查询任意的数据,这个功能是通过适配 XJSON 实现的,所以 XJSON 支持的查询语法都能实现。

string j=^{"age":10, "abc":{"def":"def"},"list":[1,2,3]}^;
String def=JSONGet(j, "abc.def");
println(def);
assertEqual(def,"def");
int l1=JSONGet(j, "list[0]");
println(l1);
assertEqual(l1,1);

string str=^
{
    "name": "bob",
    "age": 20,
    "skill": {
        "lang": [
            {
                "go": {
                    "feature": [
                        "goroutine",
                        "channel",
                        "simple",
                        true
                    ]
                }
            }
        ]
    }
}
^;
String g=JSONGet(str, "skill.lang[0].go.feature[0]");
println(g);
assertEqual(g,"goroutine");

比如这样复杂的嵌套 JSON,也能通过查询语法获取数据。

HTTP 包

HTTP 包是本次升级的重点,标准库中提供了以下函数和类:

// http lib
// Response json
FprintfJSON(int code, string path, string json){}
// Resonse html
FprintfHTML(int code, string path, string html){}

// path (relative paths may omit leading slash)
string QueryPath(string path){}

string FormValue(string path, string key){}
class HttpContext{
    string path;
    JSON(int code, any v){
        string json=JSON(v);
        FprintfJSON(code, path, json);
    }
    HTML(int code, any v) {
        string html=v;
        FprintfHTML(code, path, html);
    }
    string queryPath() {
        string p=QueryPath(path);
        return p;
    }

    string formValue(string key){
        string v=FormValue(path, key);
        return v;
    }
}
// Bind route
httpHandle(string method, string path, func (HttpContext) handle){
    // println("path="+path);
    HttpContext ctx=HttpContext();
    handle(ctx);
}
// Run http server.
httpRun(string addr){}

具体的使用流程:

  1. 通过定义一个函数变量实现自己的业务逻辑。
  2. 注册路由。
  3. 启动 HTTP 服务。

在自己的 handle 中可以通过 HttpContext 对象拿到请求上下文,可以获取请求参数以及响应数据。 具体使用示例可以参考这份代码。

总结

本次更新比我预期的要顺利一些,因为语法树和编译器已经基本实现完毕,不会怎么改了,现在新增的特性无非就是运行时实现一些语法糖,大部分都是体力劳动;可能是新鲜感带来的兴奋剂效果,大部分时间都是痛并快乐着。

比如这两天主要就是在修复多层 block 嵌套时遇到 return 语句无法正确返回的 bug,死活折腾了两夜;终于在无数次分析 AST 找到了解决方案,现在想想确实还是相关经验太少。

对这个 Bug 感兴趣的朋友可以点个赞,后面可以分享一下。

下一阶段重点就是将编译信息好好整理,让开发体验更好。之后抽空再把 SQL 标准库实现了,这样就能愉快的 CURD了。

最后希望对该项目或者是编译原理感兴趣的朋友可以下载使用,提出宝贵意见,欢迎加我微信交流。

v0.0.8 下载地址: https://github.com/crossoverJie/gscript/releases/tag/v0.0.8

都讯记者黄良东8月26日是深圳经济特区建立40周年。深圳作为全球城市经济竞争力指数排名前五位唯一中国城市,迎来了中国特色社会主义的先行示范区和粤港澳大湾区的机遇。深圳的创新精神,使得在公共服务、产业发展、政府运营方面的探索与实践一直走在全国前列,深圳的创新生态,推动深圳在探索数字经济发展上走在世界前沿,并孵化了7家世界500强企业,26家全国500强企业。

7月17日(倒计时40天),华为联合深圳特区报、南方都市报以及20多家深圳企业、机构、高校,包括比亚迪、创维、大疆创新、国信证券、哈尔滨工业大学(深圳)、华侨城、华润置地深圳、平安智慧城市、鹏城实验室、深圳北理莫斯科大学、深圳巴士集团、深圳地铁、深圳大学、深圳国际会展中心、深圳航空、深圳机场、深圳万科、深圳智慧城市集团、深圳职业技术学院、微众银行、香港中文大学(深圳)、招商蛇口等,共同发起“有你圳好,见证深圳经济特区建立40周年”系列主题活动,以“数字深圳”为场景,包括线下创意展示、线上分享,借此表达我们是深圳创新的见证者和受益者,也是创新的建设者,我们一起成长、互相成就,构筑数字深圳。

一起来看看,20多家深圳企业、机构、高校对深圳的祝福。

深圳北理莫斯科大学:作为一所全新的学校落地南国鹏城,迎接来自世界各地的你们。这里是深圳,一个极具创新精神、年轻活力、包容开放的城市。我们新办学,融合中俄教育,助你们新成长,智能未来等着你们去开拓,前进吧,少年。

OCT华侨城:作为中国唯一同时获评“全国文化企业30强”“中国旅游集团20强”的企业,央企华侨城集团35年来秉承“优质生活创想家”理念,扎根深圳、面向全国,与城共进、与城共荣,为人民美好生活持续赋能。

香港中文大学(深圳):在这里,传统与现代融合,国内与国际相联接,立足深圳,面向粤港澳大湾区,携手华为建设智慧校园,努力成长为享誉世界的中国一流学府,为师生提供更智慧、更包容、更个性化的学习体验。

微众银行:作为国内首家互联网民营银行,微众银行深度拥抱互联网的发展,踏浪而来。深圳的“智慧”已经渗入生活的方方面面,和小We一起为“数字之城”打call。

招商蛇口:四十年风雨同舟,招商蛇口见证和参与特区的开发与建设。通过“前港-中区-后城”综合发展模式,招商蛇口助力深圳从城市功能升级、生产方式升级、生活方式升级,做“美好生活承载者”。

深圳地铁:四十年来,深圳一直走在技术革新的最前端,深铁与华为联合打造数字地铁,可实现各类设备、行车、客流、服务数据的汇聚、共享、分析、呈现,极大提升地铁出行的便捷性和安全性,为市民创造更美好的“地铁生活”。

深圳大学:伴深圳成长37年,深圳大学始终发扬“特区大学、窗口大学、实验大学”的办学特色,在信息时代迎接数字化转型潮流,携华为建设智慧校园的标杆,来深大,感受智慧校园的神奇魅力。

深圳智慧城市集团: 深智城全面聚焦“新基建”和数据要素市场化配置改革,围绕数据全生命周期开展了融合韧性专网、泛在算力基础设施、智慧城市数字底座以及数据场景实验室等项目的建设和管理……致力于在数字世界打造一个更加繁荣的“数字特区”,让城市更智慧,让生活更美好。

深圳机场:与城市相伴而生的深圳机场时常出现在人们那些奋斗、奔波、相聚、重逢的珍贵回忆中。如今的深圳机场,在真情相伴的底色上,正悄然发生着“智”变。“一张脸”畅行无阻、全流程自助乘机,愿你们从机场运行、安全、服务各方面感受到“数字深圳”的智慧。

比亚迪:与你一起,坚守初心、向新而行。承载着每一个奋力拼搏的身影,感应着每一颗活力跃动的心脏,继续朝着更智慧、更美好的生活驶进。

国信证券:携手华为,重点关注新一代云数据中心、数据库、网络安全以及统一通信平台等方面的建设,实现金融科技驱动业务发展,为用户提供更智能、更有温度的金融服务。

哈工大深圳:扎根南国鹏城,依托校本部深厚的学术积淀,我们与深圳共成长。在互联网浪潮新时代,充分发挥新ICT技术建设智慧校园,为学生创造更智能、更个性化的学习体验。

深圳职业技术学院:来自全国各地的你们齐聚深圳,恰逢深圳改革开放四十周年,让我们共同见证。技能丰富的你们风华正茂、昂扬向上,同深圳一样“敢为天下先”,因为你们,深职院和深圳将变得更加美好。

鹏城实验室:深圳经济特区将在这个盛夏正式步入不惑之年,站在下一个40年的新起点上,鹏城实验室与深圳一起无惧挑战、不畏失败,以蓬勃朝气,共建鹏城辉煌。

平安智慧城市:从平安国际金融中心眺望深圳,可一览深圳四十年的巨大成就,深圳作为改革开放的窗口,迎来“当惊世界殊”的巨变,孕育了中国平安等领先企业。有你真好,深圳。

华润置地:华润置地以专业的城市运营能力,赋予城市每一寸土地新的价值。华润置地牵手深圳,相互成就,共绘未来城市新蓝图。“有你圳好”就是华润置地献给深圳最好的礼赞。

除了无数扎根深圳的企业外,每一个深圳市民,都在见证着深圳从扬帆起航到锐意创新的四十年,也感受着更智慧,更有安全感、幸福感、更惬意的城市生活。7月18至19日,该活动将在深圳书城(中心城店)旁广场南部集中展示,广大市民可前往参观并打卡深圳。

同时,华为与20多家参与机构在微信、微博等社交媒体上设置互动话题#有你圳好,见证深圳经济特区建立40周年#。欢迎广大市民转发并留言分享你与深圳的故事,精彩留言将有机会被精选展示。

从中国改革开放的先锋,到探索城市精细化管理的引领者,深圳一次又一次走在前列。华为将持续以5G、云计算、AI、大数据、物联网等新ICT技术推动深圳的数字化水平和智能化发展,实现政务高效、社区智慧、交通发达、校园平安、就医无忧,并把深圳可复制可持续的智慧城市模式带到全世界。未来深圳及粤港澳大湾区一定是中国最活跃最发达的创新发动机,成为世界创新中心。

了解更多数字深圳的信息,请点击https://e.huawei.com/topic/leading-new-ict-cn/index.html

或搜索关注华为企业业务微信、微博账号。

.使用选择器来插入内容

h2:before{

content:"前缀";

}

h2:after{

content:"后缀";

}

B.指定个别的元素不进行插入

h2.sample:before{

content:none;

}

2. 插入图像

A.在标题前插入图像文件

h2:before{

content:url(anwy.jpg);

}

B.将alt属性的值作为图像的标题来显示(用不了)

img:after{

content:attr(alt);

display:block;

text-align:center;

margin-top:5px;

font-size:11px;

font-weight:bold;

color:black;

}

3. 插入编号

A.多个标题前加入连续编号

div:before{

content:counter(divCounter);

}

div{

counter-increment:divCounter;

}

B.在项目符号中追加文字

div:before{

content:"第"counter(divCounter)"段";

}

C.指定编号样式、种类

div:before{

content:counter(divCounter,upper-alpha)'.';

color:blue;

font-size:16px;

}

D.编号嵌套

div:before{

content:counter(divCounter,upper-alpha)'.';

color:blue;

font-size:16px;

}

div{

counter-increment:divCounter;

counter-reset:subDivCounter;

}

p:before{

content:counter(subDivCounter)'.';

margin-left:15px;

font-size:12px;

}

p{

counter-increment:subDivCounter;

}

E.字符串两边添加文字嵌套符号

h3:before{

content: open-quote;

}

h3:after{

content: close-quote;

}

h3{

quotes:"【""】";

}

disc 点| circle圆圈 | square正方形 | decimal数字 | decimal-leading-zero 十进制数| lower-roman 小写罗马文字| upper-roman 大写罗马文字| lower-greek小写希腊字母 | lower-latin小写拉丁文 | upper-latin 大写拉丁文| armenian亚美尼亚数字 | georgian乔治亚数字 | lower-alpha小写英文字母 | upper-alpha大写英文字母 | none无 | inherit继承