<listing id="5x1tx"></listing>
    <track id="5x1tx"></track><pre id="5x1tx"></pre>
    <listing id="5x1tx"><strike id="5x1tx"></strike></listing>

      <del id="5x1tx"></del>

      <noframes id="5x1tx">

      <big id="5x1tx"></big>

      您的位置:首頁 >聚焦 >

      世界今日訊!里程碑!用自己的編程語言實現了一個網站

      2022-09-17 17:49:46    來源:程序員客棧
      前言

      在上一篇《終于實現了一門屬于自己的編程語言》 介紹了自己寫的編程語言 GScript ,在文中提到希望最終可以使用 GScript開發一個網站。

      到目前為止確實是做到了,首頁地址:

      https://gscript.crossoverjie.top/index


      【資料圖】

      要稱為一個網站確實有點勉強,不過也是一個動態網頁,因為返回的是 HTML,所以在當前階段只要不嫌麻煩其實也能寫一個“合格”的網站,有點像以前我們學習 Java時的 servlet。

      該頁面的源碼地址在這里:https://github.com/crossoverjie/gscript-homepage

      其實總共也就40來行代碼:

      classGScript{stringauthor;string[]features;stringsince;GScript(stringa,string[]f,strings){author=a;features=f;since=s;}}func(HttpContext)index(HttpContextctx){string[]features={"statically","strongly"};GScriptgs=GScript("crossoverJie",features,"2022");stringj=JSON(gs);println(j);stringlocal=getCurrentTime("Asia/Shanghai","2006-01-0215:04:05");println("local="+local);stringhtml=^GScript

      ______________|_|___||_|.|_-|_|_||.|_||_|___|___|_||_|_|_||___||_|v0.0.7^+j+^

      current^+local+^

      全是利用 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中也實現了。

      classPerson{intage;Person(inta){age=a;}}Personoperator+(Personp1,Personp2){Personpp=Person(p1.age+p2.age);returnpp;}Personoperator-(Personp1,Personp2){Personpp=Person(p1.age-p2.age);returnpp;}Personp1=Person(10);Personp2=Person(20);Personp3=p1+p2;println("p3.age="+p3.age);assertEqual(p3.age,30);

      聲明的函數名稱必須為 operator,之后跟上運算符便實現了重載。

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

      JSON支持

      當前版本中支持將對象、基本類型進行序列化,暫不支持反序列化為對象,但可以根據 JSON字符串通過一定的語法查詢數據。

      內置了兩個 JSON 相關函數:

      //returnJSONstringstringJSON(anya){}//JSONquerywithpathanyJSONGet(stringjson,stringpath){}

      classPerson{intage;stringname;floatweight;boolman;Person(stringn,inta,floatw,boolm){name=n;age=a;weight=w;man=m;}}Personp1=Person("abc",10,99.99,true);Personp2=Person("a",11,999.99,false);stringjson=JSON(p1);println(json);//output:{"age":10,"man":true,"name":"abc","weight":99.99}

      以這段代碼為例,調用 JSON函數可以將對象序列化為 JSON字符串。


      classPerson{intage;stringname;floatweight;boolman;Person(stringn,inta,floatw,boolm){name=n;age=a;weight=w;man=m;}}Personp1=Person("abc",10,99.99,true);stringjson=JSON(p1);println(json);intage=JSONGet(json,"age");println(age);assertEqual(age,10);

      使用 JSONGet函數可以在一個 JSON 字符串中查詢任意的數據,這個功能是通過適配 XJSON 實現的,所以 XJSON支持的查詢語法都能實現。

      stringj=^{"age":10,"abc":{"def":"def"},"list":[1,2,3]}^;Stringdef=JSONGet(j,"abc.def");println(def);assertEqual(def,"def");intl1=JSONGet(j,"list[0]");println(l1);assertEqual(l1,1);stringstr=^{"name":"bob","age":20,"skill":{"lang":[{"go":{"feature":["goroutine","channel","simple",true]}}]}}^;Stringg=JSONGet(str,"skill.lang[0].go.feature[0]");println(g);assertEqual(g,"goroutine");

      比如這樣復雜的嵌套 JSON,也能通過查詢語法獲取數據。

      HTTP 包

      HTTP 包是本次升級的重點,標準庫中提供了以下函數和類:

      //httplib//ResponsejsonFprintfJSON(intcode,stringpath,stringjson){}//ResonsehtmlFprintfHTML(intcode,stringpath,stringhtml){}//path(relativepathsmayomitleadingslash)stringQueryPath(stringpath){}stringFormValue(stringpath,stringkey){}classHttpContext{stringpath;JSON(intcode,anyv){stringjson=JSON(v);FprintfJSON(code,path,json);}HTML(intcode,anyv){stringhtml=v;FprintfHTML(code,path,html);}stringqueryPath(){stringp=QueryPath(path);returnp;}stringformValue(stringkey){stringv=FormValue(path,key);returnv;}}//BindroutehttpHandle(stringmethod,stringpath,func(HttpContext)handle){//println("path="+path);HttpContextctx=HttpContext();handle(ctx);}//Runhttpserver.httpRun(stringaddr){}

      具體的使用流程:

      通過定義一個函數變量實現自己的業務邏輯。注冊路由。啟動 HTTP 服務。

      在自己的 handle中可以通過 HttpContext對象拿到請求上下文,可以獲取請求參數以及響應數據。具體使用示例可以參考這份代碼。

      總結

      本次更新比我預期的要順利一些,因為語法樹和編譯器已經基本實現完畢,不會怎么改了,現在新增的特性無非就是運行時實現一些語法糖,大部分都是體力勞動;可能是新鮮感帶來的興奮劑效果,大部分時間都是痛并快樂著。

      比如這兩天主要就是在修復多層 block嵌套時遇到 return語句無法正確返回的 bug,死活折騰了兩夜;終于在無數次分析 AST 找到了解決方案,現在想想確實還是相關經驗太少。

      對這個 Bug 感興趣的朋友可以點個贊,后面可以分享一下。

      下一階段重點就是將編譯信息好好整理,讓開發體驗更好。之后抽空再把 SQL標準庫實現了,這樣就能愉快的 CURD了。

      最后希望對該項目或者是編譯原理感興趣的朋友可以下載使用,提出寶貴意見,歡迎加我微信交流。

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

      往期推薦

      終于實現了一門屬于自己的編程語言

      一門語言的作用域和函數調用是如何實現的

      用 Antlr 重構腳本解釋器

      用位運算為你的程序加速

      幾百行代碼實現一個 JSON 解析器

      點分享

      點點贊

      點在看

      關鍵詞: 編程語言 感興趣的 屬于自己的

      相關閱讀

      女省委书记被征服
      <listing id="5x1tx"></listing>
        <track id="5x1tx"></track><pre id="5x1tx"></pre>
        <listing id="5x1tx"><strike id="5x1tx"></strike></listing>

          <del id="5x1tx"></del>

          <noframes id="5x1tx">

          <big id="5x1tx"></big>