達特茅斯BASIC
達特茅斯 BASIC 是 BASIC 程式語言的最初版本。它由達特茅斯學院的兩位教授——John G. Kemeny 和 Thomas E. Kurtz——所設計。它以底層的達特茅斯分時系統 (DTSS) 為基礎,為所有大學部學生以及更廣泛的大學社群提供了一個互動式的程式設計環境。
達特茅斯學院曾產出數個版本,由大學部學生實作,並以編譯後即執行系統的方式運作。第一個版本於 1964 年 5 月 1 日執行,並於同年 6 月向一般使用者開放。後續的升級版本不斷推出,最終在 1979 年發布了第七個也是最後一個版本。達特茅斯學院還在 1975 年推出了一個大幅更新的版本,稱為結構化 BASIC (Structured BASIC 或 SBASIC),該版本增加了各種結構化程式設計的概念。SBASIC 成為了 1980 年代初期美國國家標準協會 (American National Standards Institute) 標準 BASIC 的基礎。
大多數 BASIC 的方言都可追溯至第四版(例如,此版增加了字串變數,大多數 BASIC 使用者認為這是理所當然的,儘管最初的版本也能夠印出字串),但通常省略了如矩陣數學等較為深奧的功能。與達特茅斯的編譯器不同,大多數其他的 BASIC 都是以直譯器的方式編寫的。這個決定使得它們能夠在早期微電腦有限的主記憶體中執行。Microsoft BASIC 就是一個例子,它被設計成僅在 4─KB 的記憶體中執行。到了 1980 年代末期,數以千萬計的家用電腦都在執行某種 MS 直譯器的變體。它成為了 BASIC 的實質標準,這也導致了 ANSI SBASIC 的努力被放棄。Kemeny 和 Kurtz 後來成立了一家公司,開發並推廣一個名為 True BASIC 的 SBASIC 版本。
許多早期的主機遊戲都可追溯至達特茅斯 BASIC 和 DTSS 系統。其中一部分遊戲被收集在 People's Computer Company 出版的《What to Do After You Hit Return》一書中,這些遊戲是 HP 分時 BASIC (HP Time-Shared BASIC) 的版本。在《BASIC Computer Games》及相關作品中,許多原始的原始碼清單也同樣源自達特茅斯 BASIC。
發展歷史
早期工作
John G. Kemeny 於 1953 年加入達特茅斯學院數學系,後來成為系主任。1956 年,他透過麻省理工學院的新英格蘭地區電腦中心計畫,得以接觸到一台 IBM 704。那年,他編寫了 DARSIMCO 語言,這是一種簡化了數學運算程式設計的組合語言版本。協助他的是同年加入該系的 Thomas E. Kurtz。
當第一套 FORTRAN 編譯器於 1957 年安裝在該機器上後,DARSIMCO 就被遺忘了。FORTRAN 的出現帶來了一個重要的教訓。Kurtz 曾被灌輸 FORTRAN 速度很慢的觀念,他花了好幾個月用 704 組合語言編寫一個程式,該程式花了大約一小時的 CPU 時間來除錯,但仍然無法執行。在放棄之後,他用 FORTRAN 重新編寫,並在五分鐘內讓它成功執行。這個教訓是,高階語言可以節省時間,無論其測量出的效能如何。
1959 年,學校購得了第一台電腦,即以磁鼓為基礎的 LGP-30。一名學生為這台機器編寫了一種受 FORTRAN 啟發的語言,名為 DART。這促使了一個開發 ALGOL 58 編譯器的計畫,並在 ALGOL 60 定義最終確定後轉向該版本。由於記憶體極小(以現代術語來說是 32─KB),編寫編譯器非常困難,而且基於 3600 rpm 的磁鼓速度,執行速度極慢。儘管如此,他們還是成功製作出一個功能性的精簡版本,稱為 ALGOL 30。進一步的開發產生了 SCALP,即「獨立 Algol 處理器 (Self-Contained Algol Processor)」,這是一個單遍編譯器,一旦打孔紙帶讀完原始碼,就能立即執行編譯好的程式。包含程式結果或任何錯誤訊息的輸出會立刻出現。這種編譯後即執行的操作風格後來被 BASIC 所採用。
1962 年,Kemeny 和高中生 Sidney Marshall 開始實驗一種新語言,名為 DOPE(Dartmouth Oversimplified Programming Experiment,達特茅斯超簡化程式設計實驗)。它使用編號行來表示指令,例如,要將兩個數字相加,DOPE 使用:
5 + A B C
這意味著「在第 5 行,執行變數 A 和 B 中值的加法,並將結果放入 C」。儘管佈局有些晦澀,但未來 BASIC 語言的基礎已可見一斑。除了基本的數學運算,該語言還包括 SQR、EXP、LOG、SIN 和一個簡單的分支結構。
文科教育中的運算
Kemeny 和 Kurtz 一致認為,傳統 STEM 領域以外的學生也需要具備程式設計素養;達特茅斯學院只有 25% 的學生修讀 STEM 相關課程,但幾乎每個領域都會使用到某種程度的數學。此外,隨著電腦在社會中變得越來越重要,他們不禁思考:「一個對運算基本無知的人,如何能對運算及其使用做出明智的決定?」
Kemeny 後來指出:「我們的願景是,校園裡的每個學生都應該能接觸到電腦,任何教職員都應該能在課堂上適時使用電腦。就這麼簡單。」但以他們當時擁有的資源來看,要做到這一點幾乎是不可能的;一次典型的 SCALP 執行週轉時間約為 15 分鐘,而且這些語言對於非 STEM 使用者來說,用來完成基本任務實在太困難了。
問題不僅在於複雜性,更在於批次處理的整個概念。學生們會在打孔卡或紙帶上準備好他們的程式,提交給電腦操作員,然後在未來的某個時間點收到他們的輸出。這常常會暴露出一個錯誤,需要重複整個過程。正如他們後來所說:「如果一次嘗試需要大約一天的時間,學生要嘛會失去興趣,要嘛會忘記問題所在。最好的情況下,他也只是浪費時間站著等待當天的結果出來。」
1959 年,主要由於 Kemeny 作為數學教學創新者的聲譽,該系贏得了艾爾弗·斯隆基金會 50 萬美元的獎金,用於建造新的系館。
發展概念
在 1961 年一次訪問麻省理工學院期間,他們接觸到了 PDP-1 及其最近完成的實驗性分時作業系統。John McCarthy 問 Kurtz,他們為何不用分時技術來實現將運算普及大眾的目標。Kurtz 回到達特茅斯告訴 Kemeny「我們應該做分時」,Kemeny 立刻回答「好」。
為了測試這個概念是否可行,他們進行了一項實驗,將學生分成五人一組,輪流在 LGP-30 上使用 SCALP。電腦時間被分成 15 分鐘的時段,每組五人獲得一個時段,然後交給下一組。結果發現,學生們通常在一個時段內經過兩到三次「週轉」就能完成他們的程式。這清楚地表明,一個互動式系統可以讓數百名使用者成功地使用一台機器。
電傳打字機 Teletype Model 33 的出現,使用新引進的 ASCII 透過電話線傳輸,解決了存取問題;程式設計師不再需要在卡片或紙帶上提交程式,他們現在可以使用 Model 33 直接向電腦輸入。所需要的只是一台速度足夠快以承載分時系統的新機器,以及一種供程式設計師使用的簡單語言。
當開始認真考慮一種簡單語言這個議題時,Kemeny 立刻建議編寫一種新的語言。Kurtz 則對 FORTRAN 或 ALGOL 的精簡版本更感興趣。但這些語言有太多特性,以至於 Kurtz 也開始同意 Kemeny 的看法:
隨著時間推移,四個關鍵要素浮現出來:系統將使用分時技術;需要一種新的語言;為了讓使用者上手,新的課程將把程式設計作為其他學科的輔助內容來介紹;最後,終端機將對所有使用者開放。
初始版本
該計畫於 1963 年 9 月正式啟動。目標是在一台現成的電腦上開發語言和作業系統。1964 年初,他們向國家科學基金會 (NSF) 申請資金。NSF 將提案——一份關於分時系統,另一份關於語言——送交同儕審查。審查意見無一例外地認為他們不了解自己嘗試任務的難度。儘管有這些負面評論,NSF 還是批准了這兩項資助。通用電氣 (General Electric) 提供的教育折扣促成了 GE-225 電腦的採購,在那個不「選用 IBM」仍充滿風險的年代。
GE-225 與更簡單的 DATANET-30 (DN-30) 機器配對,並有一台硬碟連接到兩台機器以共享程式。當時 DN-30 缺乏任何程式設計文件,因為它從未打算在出廠時不安裝程式。它包含一個關鍵特性:對較大的 GE 機器進行直接記憶體存取 (DMA)。這意味著小訊息可以在機器之間快速來回傳遞,讓使用者輸入的指令能立即由 225 執行。
該系統的運作方式是讓 DN-30 執行終端機並將使用者的工作儲存到磁碟上。當使用者輸入 `RUN` 時,DN-30 會使用 DMA 將該指令傳送給 GE-225。225 會讀取該檔案,進行編譯、執行,並將結果傳回給 DN-30,然後在終端機上印出輸出。
1963 年夏天,在等待電腦採購期間,GE 提供了一台他們的 GE-225 供使用。Kemeny 開始著手開發一個原型編譯器。同年秋天,學生 Michael Busch 和 John McGeachie 開始進行作業系統的設計。在此期間,語言和作業系統都經過了大量修改,儘管基本目標保持不變,並於該年 11 月以草案形式發布。
學校的機器於 1964 年 2 月的最後一週運抵,3 月中旬投入運作,並於 4 月 1 日正式移交。那時,作業系統的設計已經相當成熟。大多數參與作業系統開發的學生程式設計師每週工作 50 小時,此外還要應付正常的課業負擔。語言則是在另一台 225 機器上借用時間並行開發的。作業系統於 4 月完成,整個系統在三個 Model 33 終端機上運作,並於月底準備就緒。John Kemeny 和 John McGeachie 於 1964 年 5 月 1 日美國東部時間凌晨 4 點執行了第一個 BASIC 程式。
第一個程式具體是什麼並不完全清楚。許多來源,包括達特茅斯學院,都聲稱是這個簡單的程式:
PRINT 2 + 2
後來的一部語言史記載,當時有兩個程式同時被輸入,一個由 Kemeny 輸入,另一個由一位未具名的程式設計師輸入。他們輸入了各自的程式,同時輸入 `RUN`,並得到了正確的結果。Kurtz 是個早起的人,已經回家,「錯過了所有的樂趣」。
在接下來的一個月裡,系統透過讓一個數值分析班級在系統上測試程式來進行檢驗。在此期間,機器平均能正常運作五分鐘。問題很快得到解決,並在 6 月決定將終端機數量增加到十一台。大約在這個時候,一台更快的 GE-235 取代了 225。到了秋天,已有 20 台終端機投入使用。
GE 開始將 GE-235 和 DN-30 的組合稱為 GE-265,將它們的型號數字相加。GE 又製造了大約 75 台 GE-265 的例子,許多用於他們的服務局業務。GE 將這些系統稱為他們的 Mark I 分時系統。
新系統
該計畫的最初目標之一是將程式設計融入其他課程中。這項嘗試很成功,但也給系統帶來了相當大的壓力,顯然它已沒有未來發展的空間。
1965 年,團隊向 GE 尋求持續開發的支援。9 月,副總裁 Louis Rader 提供了新的 GE-635,其執行速度約快 10 倍,並包含兩個 CPU。此外,還將增加第二台 DN-30 以處理更多線路,足以容納 150 名同時上線的使用者。為了安置它,需要比 265 所在的學院廳地下室更大的設施。在 22 屆校友 Peter Kiewit 以及 NSF 的額外支持下,Kiewit 運算中心得以建造,並於 1966 年 12 月啟用。
在等待這台機器運抵期間,1966 年的夏秋兩季,團隊利用羅馬航空發展中心的一台 GE-635 開發了 MOLDS,即「多使用者線上除錯系統」(Multiple User On-Line Debugging System)。GE-635 於 1967 年初投入運作,利用 MOLDS,新的作業系統在 9 月全面運作,屆時 GE-265 被售出。
GE 免費提供了這台機器三年,作為一項更廣泛協議的一部分,根據該協議,達特茅斯將開發新版本的 BASIC,而 GE 則利用它來開發其作業系統版本的新版本。這次合作證明是成功的;GE 開始將這些機器部署為其 Mark II 分時系統,到了十年末,他們已成為全球最大的分時服務供應商之一。
當這個「第一階段」系統投入運作後,達特茅斯團隊開始開發「第二階段」,即理想的作業系統。它於 1969 年 3 月安裝,並在不久後更名為達特茅斯分時系統。三年期滿後,GE 將機器贈送給了該大學。儘管兩個團隊保持聯繫,並進行了幾次真誠的嘗試以繼續合作關係,但幾乎沒有進一步的合作,夥伴關係於 1972 年 9 月 20 日正式結束。
擴大使用者群
1968 年的一份回顧指出,80% 的學生和 70% 的教職員都在某種程度上使用該系統。數百個終端機遍佈校園,從醫院到商學院。57% 的 CPU 時間用於課程作業,16% 用於研究,剩下的 27% 用於「娛樂用途」;達特茅斯積極鼓勵使用者玩遊戲,以此作為親身實踐和克服對電腦恐懼的方式。
從另一筆 NSF 撥款開始,達特茅斯於 1967 年也開始在校外地點設置終端機,包括該地區的高中。就使用者數量而言,這些終端機佔了總使用者的 69%,儘管他們使用的電腦時間較少。到 1971 年,已有 79 個遠程終端機,遠至新澤西州和緬因州的班戈。這些終端機由多工器系統支援,允許最多 12 個終端機透過單一語音級電話線得到支援。此外,其中一些線路可供使用數據機進行撥接使用。
影響
分時技術是 1960 年代的一個主要研究領域,電腦行業中許多人預測運算能力將變得廉價而普及。最著名的陳述來自 John McCarthy,他說:「運算有朝一日可能會像電話系統一樣,作為一種公用事業來組織。」
雖然 DTSS 上也有其他語言可用,但 98% 的程式都是用 BASIC 編寫的。有了 BASIC,電腦服務對於那些任務編碼耗時過長、不適合在電腦上解決的終端使用者來說,變得更加容易取得。這導致許多製造商推出了專為這個市場設計的電腦,這些使用者希望解決中小型任務,而不太關心絕對的效能。特別是,兩款直接針對這個市場的機器成為了「有史以來使用最廣泛的小型分時系統」。
HP 2000 執行 HP 分時 BASIC (HP Time-Shared BASIC),這是一個 BASIC 和分時作業系統的組合,幾乎與 DTSS 的設定相同。該系統最多可支援 32 個同時上線的使用者,使用低階的 HP 2100 CPU 來執行終端機,方式與原始 GE-265 的 Datanet-30 相同,而程式則在同一機器的更高階型號上執行,其差異通常在於擁有更多的核心記憶體。HP 的 BASIC 使用一種半編譯的符號化格式來儲存程式,這改善了載入時間,並意味著「編譯」是零時間的。
迪吉多公司 (Digital Equipment Corporation) 採取了不同的方法,使用基於其現有 PDP-11 系列的單機產品,配備新的 RSTS/E 作業系統和 BASIC-PLUS。BASIC-PLUS 更緊密地遵循第五版,包括 `MAT` 指令,但它是以純直譯器的方式實作,而不是像達特茅斯編譯器或 HP 的符號化格式。它還包括一些遵循 JOSS 模型的控制結構,例如 `<陳述式> IF <條件式>`。Tymshare SUPER BASIC 也支援 JOSS 風格的結構和矩陣數學,但保留了原始的編譯後即執行操作。
當時幾乎每個供應商都針對同樣的問題提供了某種解決方案,儘管它們可能不像原始版本那樣相似。當 Kurtz 於 1973 年開始考慮為 BASIC 制定 ANSI 標準時,他發現提供 BASIC 的分時服務局數量比任何其他語言都多。不幸的是,這種成功也是一個問題;到那時,變體已經太多,以至於制定一個標準似乎是不可能的。
BASIC 遊戲
Kemeny 積極鼓勵在 DTSS 平台上開發遊戲,並認為這是 DTSS 系統成功的主要原因之一。他很可能是某款早期主機遊戲的作者。雖然 Kemeny 沒有為此居功,但他後來提到 FTBALL 時說,它「是在 1965 年某場達特茅斯對普林斯頓的比賽後的一個星期日寫的,當時達特茅斯贏得了蘭伯特獎盃。這算是一個紀念性的程式」。那場比賽是達特茅斯爆冷擊敗了備受看好的普林斯頓。
隨著系統的擴展,特別是在 BASIC 中增加了字串處理功能之後,DTSS 系統成為了許多文字遊戲開發的主要平台。在 1970 年代初期,人民電腦公司 (People's Computer Company) 開始在其雜誌上發表這些遊戲,通常會轉換成更普及的 HP BASIC。其中許多列表被收錄在他們 1975 年出版的《What to do after you hit return》一書中。儘管這些遊戲以 HP BASIC 的形式發布,但它們中的大多數都可追溯至 DTSS 或加州的勞倫斯科學館,那裡也設置了一台類似的機器,稱為 DECISION。
一個更著名的合集是 1978 年的《BASIC Computer Games》,書中約有一半的程式要嘛是在達特茅斯編寫的,包括 Kemeny 的另一款遊戲 Batnum,要嘛更常見的是,來自 1968 年後與之連接的眾多高中之一。麻薩諸塞州的列星頓高中 (Lexington High School) 是一個特別多產的高中,但許多其他學校也出現在其中。一些程式沒有列出其原始地點,但其作者很可能透過學校或像 SOLO 計畫這樣的公共項目與該系統有所聯繫。
當 Stephen Garland 和 John McGeachie 為 DTSS 開發了 MOTIF 多使用者線上終端機介面 (Multiple Online Terminal Interface) 後,多人視訊遊戲在 BASIC 中成為可能。要開始一個遊戲,使用者輸入 LINK 後面跟著一個會話名稱,而不是 RUN,這樣其他使用者就可以透過輸入 JOIN 後面跟著會話名稱來連接到遊戲。MOTIF 接著會為 BASIC 程式多工處理輸入和輸出,在每行輸入和輸出的開頭加上一個字串識別碼。用這個介面開發的第一批程式是一個兩人版的 FTBALL 和一個五人撲克遊戲。更嚴肅的是一個管理遊戲,它允許多達十名艾默斯·塔克工商管理學院的學生在單一產品的生產和行銷中進行競爭。
版本
第一版
最初的版本,後來被追溯稱為第一版,支援 `LET`、`PRINT`、`END`、`FOR...NEXT`、`GOTO`、`GOSUB...RETURN`、`IF...THEN`、`DEF`、`READ`、`DATA`、`DIM` 和 `REM` 等指令。它包含基本的數學指令 `+`、`-`、`*`、`/` 和 `^`,以及用於指數的上箭頭「...因為在電傳打字機上不可能印出上標。」在現代的變體中,上箭頭通常被「帽子」字元 `^` 所取代。指數運算會在計算前取數字的絕對值,所以要計算 `x^-2`,必須使用 `1/x^2`。指數函數還有一個問題,它將 `-A^B` 處理為 `(-A)^B`,而不是正確的運算順序 `-(A^B)`,這個問題直到第三版才被修正。`INT()` 函數總是向零截斷。
該語言本身有一些特點。與後來的版本相反,所有沒有其他指令的陳述式都必須使用 `LET` 指令,所以 `A=5` 在此版本中是無效的。`PRINT` 陳述式在印出多個變數時使用逗號,這會前進到五個「區域」中的下一個。在印出提示和單一值的情況下,逗號不是必需的,所以 `PRINT "THE VALUE IS",V` 是有效的。一個有些隱藏的特性是,所有變數都能夠表示多達十個元素的陣列(向量)(下標從 1 到 10,在第二版中改為 0 到 9),而無需使用 `DIM` 進行宣告。只有在需要不同大小的向量時才需要 `DIM`。
變數名稱被限制為單一字母或一個字母後跟一個數字(286 個可能的變數名稱)。使用者函數只能有一個字母,因此是 `FNA` 到 `FNZ`。所有運算都以浮點數進行。在 GE-225 和 GE-235 上,這產生了大約 30 位元(約十位數字)的精度,其以 2 為底的指數範圍為 -256 到 +255。
此外,由於 GE-235 的字組大小為 20 位元並使用六位元字元碼,該語言確立了使用三個字母的函數名稱,因為這允許在一個 20 位元的字組中儲存三個六位元的字元(使用 18 位元)。這就是為什麼 BASIC 的函數是三個字母,如 `INT` 或 `SQR`,這個特點在該語言的許多變體中一直保留,遠在它們離開 GE-235 之後。
第二版,CARDBASIC
BASIC 的第二版(當時並非如此稱呼)只做了極小的改動。它於 1964 年 10 月發布,可以讓陣列的下標從 0 開始而不是 1(這對於表示多項式很有用),並在 `PRINT` 陳述式中加入了分號 `;`。與後來的實作中分號會在項目之間留下空格不同,這裡的分號會將印出位置前進到下一個三字元的倍數,這對於在一行輸出中「塞入」比現有逗號分隔符更多的數字很有用。三字元的大小是 GE-235 的 20 位元字組大小的副作用,它儲存了三個六位元的字元。跳到下一個三字元欄位僅僅是透過移動到記憶體中的下一個字組來實現的。
十月份的版本還包括了 CARDBASIC 的一個單獨定義,這只是 BASIC 的一個用於基於卡片工作流程的版本。CARDBASIC 與互動式版本幾乎相同,唯一的例外是它不包括以零為基礎的陣列。對語言未來更重要的是,CARDBASIC 增加了處理數值矩陣的 `MAT` 指令。CARDBASIC 沒有被進一步開發,因為 BASIC 的整個理念就是互動式的。
第三版
第三版於 1966 年發布,是第一個使用「版」這個名稱的版本,也是第一個專為即將到貨的新 GE-635 電腦設計的版本。此版本包含了來自 CARDBASIC 的 `MAT` 函數,並且它們現在可以使用 0 作為下標。
新的 `SGN` 函數給出其參數的符號(正數→1,零→0,負數→-1),而 `RESTORE` 被加入以「倒回」`READ/DATA` 的位置。指數運算的問題被修正了,所以 `-A^B` 會被解釋為 `-(A^B)`。此外,`INT` 函數被更改為真正的無條件捨去(floor),而不是向零截斷,這使得可以用 `INT(X+0.5)` 來實現四捨五入。
此版本的主要變更是新的 `INPUT` 陳述式,它可以解析數值,使語言在執行期間首次真正實現了互動;在此之前,執行期間唯一的控制是在監控器中輸入 `STOP`。此外,系統現在允許並鼓勵迴圈縮排,這個功能在大多數其他版本的 BASIC 中是看不到的。
第四版
第三版在 GE-235 的整個生命週期中一直使用到 1967 年秋天。然而,隨著接收 GE-635 的計畫制定,1967 年春天在 635 上創建了一個實驗版本。這個版本是 GE 和達特茅斯學院的合作成果,GE 貢獻了一個新的作業系統以及他們自己的 Mark 1 BASIC 中的一些 BASIC 功能。
這個版本最初作為第三版的補充發布,增加了 `RANDOMIZE` 指令來為 `RND` 函數「播種」,以及 `ON...GOTO`「計算型 goto」,這與 FORTRAN 中類似的功能非常接近。這個版本也允許 `ON...THEN`,理由是如果 `IF...THEN` 不需要 `GOTO`,那麼這裡也就不需要。新的 `TAB` 函數將印出位置移動到給定的欄位,從 0 到 74。另一個內部變更是再次將 `MAT` 改為從 1 開始;雖然可以使用第 0 個索引,但通常會被各種指令忽略。
此版本的主要新增功能是字串變數,以及對 `READ/DATA` 陳述式的更改,使其可以儲存字串,並對 `INPUT` 陳述式進行更改以互動式地讀取它們。字串系統的一個特點是,在比較時故意忽略尾隨的空格,所以 "YES" 和 "YES " 被認為是相等的。這後來被認為是一個嚴重的錯誤。字串變數用美元符號 `$` 表示,原因很簡單,因為他們快要用完在大多數鍵盤上能找到的字元了。有人指出 `$` 看起來像 "String" 中的 S,於是就這麼定了。
字串操作是透過新的 `CHANGE` 指令來處理的。它將變數中的字串值轉換為等效的 ASCII 值集合。然後可以操作這個數字陣列並將其轉換回字串。例如,這段程式碼在控制台上產生 "is":
140 行將字串長度設置為 2,這必須由使用者管理。第一個字元在 T(1) 中。雖然這個系統很靈活,但使用起來絕不方便。後來的版本將用新的功能來解決這個問題。
此版本中的微小變化將 `PRINT` 陳述式中的分號改為進行「緊密排列」輸出,不帶空格,並使用單引號作為 `REM` 的簡寫形式。
正式的第四版直到 1968 年才出現,它在先前新增功能的基礎上又增加了一些新功能。這包括使用 `DEF` 指令定義多行函數的能力,以及強大的 `CHANGE` 陳述式,它將字串視為類 ASCII 碼的陣列,因此可以在不遍歷整個字串的情況下對單個字元進行操作。這也是唯一的字串操作函數;要提取單個字元或子字串,必須使用 `CHANGE` 將其轉換為數字陣列,操作該陣列,然後再將其轉換回來。這就是為什麼 MAT 再次從 1 開始;字串的長度被放在位置零,而它需要被正常忽略。
第五版
第五版來自 1970 年末,最初也是作為第四版的兩個補充,分別來自 1969 年 2 月和 4 月。
主要的變更是引入了檔案處理。以前,程式中需要使用的任何預定義資料都必須放在 `DATA` 行中,然後使用 `READ` 指令逐一讀入。這個功能可以用類似的方式來讀取檔案。`READ` 指令現在可以從檔案中讀取單個項目,而 `WRITE` 可以寫入一個。
檔案是透過新的 `FILES` 關鍵字打開的,後面跟著一個描述檔案名稱的字串常數列表。由於這些是常數,更改檔案名稱需要修改程式碼以匹配。這些名稱被分配了數字,第一個名稱成為檔案 #1,依此類推。支援兩種檔案格式:隨機存取和線性。線性檔案的處理方式就像今天的文字檔案一樣,可以 `READ #1, A$` 將一行文字讀入一個字串變數,然後 `PRINT A$` 將其輸出到終端機。後來的版本增加了 `FILE` 來允許用字串指定檔案,儘管有一段時間這需要在程式頂部附近加上一個 `FILES *` 來表示你正在使用這種格式。
對於隨機存取檔案,名稱必須指定其中的資料類型;`TYP` 表示它包含二進位資料,而 `STR` 表示它應該被讀取為最大長度為 `<n>` 的字串。`READ` 和 `WRITE` 可以使用 `RESET` 指令定位在隨機存取檔案的任何位置,而當前位置由 `LOC` 函數返回,檔案長度由 `LOF` 返回。在循序讀取期間,也可以使用 `IF END THEN...` 來測試是否已到達檔案末尾。
另一個主要變更是,一個 BASIC 程式可以使用 `CHAIN` 指令呼叫另一個程式,並使用 `WITH` 列表將變數傳遞給它。後來人們意識到這個基本概念存在一些問題,但它仍然被用來編寫一些大型程式。
字串處理獲得了重大更新。新的 `SEG$` 指令返回一個從另一個字串中剪切出來的新字串。在上面的例子中,字串 "is" 是從一個更大的字串中提取的。使用新的指令,這可以簡化為 `SEG$(A$,2,3)`,其工作方式類似於大多數方言中的 `MID$` 函數(`SEG$` 使用起始和結束索引;`MID$` 使用起始索引和長度)。`LEN` 返回字串的長度,這現在在內部處理,在大多數情況下不需要計算,而 `POS` 返回一個字串在另一個字串中的位置,這在大多數方言中是由 `INSTR` 處理的。& 符號被引入用於字串串接。
還增加了許多較小的變更。其中包括二維字串陣列,而不是前一版本中的一維,以及使用 `DEF` 來定義基於字串的函數和數學函數的能力。新的系統導向函數包括 `CLK$`、`TIM$` 和 `DAT$` 用於處理時間和日期,`TIME` 返回經過的時間,以及 `IDN$` 返回使用者編號,即今天的用戶名。新的字串函數包括 `STR$`、`VAL`、`TRM$`,這些在現代 BASIC 方言中很常見。`'` 作為 `REM` 的簡寫形式也出現在此版本中。
第六版
第六版的工作在第五版最終確定之前的 1969 年秋天就開始了。新版本的事先完整規格書已經寫好。這與以前的版本形成對比,以前的規格文件是基於編譯器的變更而制定的。這個版本由 Kemeny 和 Kurtz 以及幾位作為教員回歸的前學生共同開發:Stephen Garland、John McGeachie 和 Robert Hargraves。它被給予了充足的時間來成熟,在 1971 年夏天有一個測試版運行了三個月,然後才於 1971 年 9 月 21 日正式發布。由於這種成熟度,Kurtz 將其描述為「可能是達特茅斯有史以來設計最好、最穩定的軟體系統」。
最大的變革之一是用定義更明確的 `CALL` 取代了早期的 `CHAIN` 概念,`CALL` 的操作方式類似於 `GOSUB`,但它引用的是函數名稱而不是行號。函數是使用 `SUB...SUBEND` 定義的,並在呼叫中接受任意參數,而不是透過 `COMMON` 宣告使用全域變數。另一個主要變更是使用 `FILE` 指令創建的檔案控制代碼(數字),這與大多數現代 BASIC 中的 `OPEN` 相似。`PRINT USING` 提供了類似於 FORTRAN 的格式化輸出,而 `LINPUT` 則接受未經解釋的輸入,允許輸入逗號、分號,甚至 BASIC 程式碼。
第六版基本上是原始 BASIC 概念的最後一個版本。它多年來保持不變。後來的版本是顯著不同的語言。
SBASIC
1976 年,Stephen Garland 收集了一些結構化程式設計的附加功能,創建了達特茅斯結構化 BASIC (Dartmouth Structured BASIC),或稱 SBASIC。其主要目標是用各種區塊導向的結構取代基於 `IF...THEN` 和 `GOTO` 的控制結構。它透過一個預編譯器來實現這一點,該預編譯器接收 SBASIC 原始碼,將其轉換為第六版 BASIC,然後像往常一樣編譯並執行。SBASIC 還增加了一些圖形功能,基於其他程式設計師添加的 `PLOT` 指令。
區塊結構由匹配的陳述式終止,就像 ALGOL 68 的情況一樣,而不是像 Pascal 或 C 這樣的語言中常見的通用區塊結構。例如,`DO WHILE...` 會跨越多行,直到以 `LOOP` 結束。`DO` 迴圈也可以透過移除 `WHILE` 或 `UNTIL` 並將條件式放在 `LOOP` 的底部來從底部退出。無限迴圈則使用 `DO FOREVER` 或 `LOOP FOREVER` 來支援。
「原始」的達特茅斯 BASIC 不允許在 `THEN` 後面有陳述式,只允許有要跳轉到的行號。SBASIC 允許任何陳述式,例如 `IF X>5 THEN PRINT "X is large"`。這種對 `IF...THEN` 的基本擴展,在 1972 年由 BASIC-PLUS 首創,到此時已廣泛被大多數 BASIC 變體所支持,包括當時正在發布的微電腦版本。在此之上,SBASIC 透過將 `THEN` 放在單獨的一行,然後用 `CONTINUE` 結束區塊,來增加區塊導向的 `IF`。除此之外,SBASIC 還增加了 `SELECT CASE` 機制,這個機制至今仍在 Visual Basic .NET 中存在。
SBASIC 還增加了一些旨在與繪圖機一起使用的圖形指令。這需要 `PLOTTER "plottername"` 來將後續指令導向到選定的設備,以及 `WINDOW...` 來設置其參數。從那時起,`PLOT X,Y` 會在選定的繪圖機上產生點,而在陳述式末尾加上分號(如 `PRINT` 中所用)則會讓筆留在紙上並產生一條線,例如 `PLOT 10,10;20,20`。
SBASIC 最終成為 1987 年 ANSI X3.113-1987 完整 BASIC 標準的基礎,該標準擴展了早期的 1978 年 ANSI X3.60-1978 最小 BASIC 標準。制定該標準的漫長延遲,以及電腦科學家對非結構化 Basic 的不重視,導致由 Garland 主持的大學理事會 AP 電腦科學課程開發委員會選擇要求使用 Pascal,而不允許 Basic 作為該課程的語言。
Garland 使用 SBASIC 來教授達特茅斯學院的電腦科學入門課程,但他用 Pascal 重寫了該課程的教科書,以便可以用於教授 AP 課程。
第七版
Garland 的 SBASIC 是一個用 SBASIC 原始碼本身編寫的預編譯器。系統會讀取 SBASIC 原始碼,寫入相應的第六版程式碼,然後編譯該輸出。第七版於 1980 年發布,是 SBASIC 的一個獨立編譯器版本。它自身也增加了一些附加功能。大多數變更都是對呼叫外部程式和可用於將程式分解為多個部分的「覆蓋層」系統的進一步闡述。在這個版本中,共享單一檔案的 `SUB` 實際上在它們之間共享資料。這在例程組內提供了一定程度的資料隱藏。這種分離今天被稱為模組。
此外,此版本還增加了結構化錯誤處理和 `LET` 陳述式中的任意矩陣數學運算,因此可以寫 `LET A = M*4`,其中 M 是一個矩陣變數,該陳述式會將 M 中所有元素乘以 4 後,輸出另一個矩陣到 A 中。最後,另一個重大更新是為子程式使用活化記錄,這使得遞迴成為可能。
ANSI BASIC,第八版
到 1970 年代初,BASIC 的實作數量已增至數十種,所有這些都對原始版本引入的基本概念進行了自己的修改。其中大多數基於第五版,儘管它們通常缺少 MAT 指令和縮排程式碼的能力。GE 就是其中之一;他們發布的 Mark II 系統採用了第五版,而不是等待幾個月後第六版的到來。DEC 平台上的 BASIC-PLUS 或許是最接近的實作,例如它包含了 MAT 指令,但也增加了一些不向後相容的變更。
在第六版發布後,Kurtz 參與了一項定義標準 BASIC 的工作。一個美國國家標準協會 (ANSI) 工作組 X3J2 於 1974 年 1 月成立,一個相應的歐洲電腦製造商協會 (ECMA) 工作組 TC21 則於同年 9 月成立。當時的目標是產生兩個相關的標準。最小 BASIC 將類似於第二版,但增加了字串,這是一個幾乎所有 BASIC 都已經能夠符合的標準。標準 BASIC 將增加更多功能,以產生更符合市場上實際 BASIC 變體的東西。
這個過程很緩慢,最小 BASIC 的第一份草案直到 1976 年 1 月才發布,導致它在 1977 年 12 月被 ECMA 正式採納,並在 1979 年被 ANSI 採納為 X3.60-1978。最小 BASIC 類似於第三版,包括字串變數,但缺少 MAT 和其他進階功能。相比之下,標準 BASIC 有許多在其他 BASIC 中不存在的新功能,其中許多考慮不周,並受到一些批評。例如,該標準包含一個續行字元,但選擇了 & 符號,而該符號也用於字串串接。在單行中使用這些可能會導致非常混淆的程式碼。
此時,1975 年第一批微電腦系統的發布迅速導致了 Altair BASIC 的引入,這是後來被稱為 Microsoft BASIC 的第一個版本。MS BASIC 模仿了 BASIC-PLUS,因此最終源自第五版,但缺少縮排、MAT 和其他功能。它還增加了 `LEFT$` 和 `RIGHT$` 函數,打破了三個字母的慣例。隨著微電腦數量的增長,並在 1970 年代末轉變為家用電腦市場,MS BASIC 成為了實質上的標準。
隨著市場的這種快速變化,標準 BASIC 的工作進一步放緩,直到 1987 年才被正式批准為 X3.113-1987。到此時,這些標準已無實際意義;不僅 MS BASIC 無處不在,而且到 1980 年代中期,隨著套裝軟體取代了手動輸入的程式,BASIC 的使用也在下降。這兩個標準最終都被撤銷。
儘管 ANSI 的努力最終失敗,標準 BASIC 的草案還是於 1982 年在達特茅斯作為第八版被實作。
DTSS 介面
DTSS 實現了一個早期的整合開發環境 (IDE):一個互動式的命令列介面。它提供了一些使用者和作業控制指令。例如,一個閒置的終端機可以透過輸入 `HELLO` 連接到一個使用者帳戶,並用 `BYE` 再次登出。
使用者輸入的任何以行號開頭的行都會被添加到程式中,取代任何先前儲存的相同行號的行;任何其他內容都被假定為 DTSS 指令並立即執行。僅由行號組成的行不會被儲存,但會移除任何先前儲存的相同行號的行。由於使用電傳打字機作為終端單元,這種編輯方法是必要的。
每個使用者帳戶可以有任意數量的 BASIC 程式離線儲存,而管理員帳戶也可以將程式永久儲存。對於給定的使用者帳戶,在任何給定時間只有其中一個程式是活動的,如果沒有載入程式,則假定為一個新程式。儲存的程式是透過今天更為人所知的 BASIC 語言本身的指令來存取的;例如,`LIST` 指令指示 DTSS 印出當前活動的程式。
指令列表
- `HELLO`
- 登入 DTSS
- `BYE`
- 登出 DTSS
- `BASIC`
- 啟動 BASIC 模式
- `NEW`
- 命名並開始編寫程式
- `OLD`
- 從永久儲存中檢索先前命名的程式
- `LIST`
- 顯示當前程式
- `RUN`
- 執行當前程式
- `STOP`
- 中斷當前執行的程式
- `TEST`
- 使用教師提供的程式來測試當前程式
- `LINK`
- 在多終端模式下執行當前程式
- `JOIN`
- 加入一個在多終端模式下執行的程式
- `SAVE`
- 將當前程式儲存在永久儲存中
- `UNSAVE`
- 從永久儲存中清除當前程式
- `REPLACE`
- 使用已用於另一個檔案的名稱儲存當前程式
- `CATALOG`
- 顯示永久儲存中的程式名稱
- `SCRATCH`
- 清除當前程式但不清除其名稱
- `RENAME`
- 更改當前程式的名稱而不清除它
- `FRI`
- 為具有機械換行功能的電傳打字機啟用 Friden 模式
- `NFR`
- 禁用 Friden 模式
- `EXP`
- 解釋 (幫助);`EXP EXP` 可列出系統可以解釋的指令列表
使用者通常認為這些指令是 BASIC 語言的一部分,但事實上,它們是分時系統的一部分,在透過 DTSS 終端機準備 ALGOL 或 FORTRAN 程式時也會使用。
TEACH/Test 系統
在 1960 年代末,約 80% 的達特茅斯學生都修讀兩門數學課程,並在第二門課程中學習 Basic,無論是微積分還是有限數學。他們在這些課程開始時會聽兩堂一小時的 Basic 講座,然後必須用 Basic 編寫四個程式,範圍從近似 π 或求五次多項式的根的程式,到解微分方程或(透過模擬)求馬可夫鏈中極限概率的程式。TEACH/Test 系統幫助學生完成這些作業。當他們認為自己的程式可以運作時,他們會輸入 TEST 指令,然後一個由教師編寫的程式要嘛會批准他們所寫的,要嘛會提示他們可能在哪裡出了錯。學生被要求交出每個程式的列表、一個範例 RUN,以及來自 TEACH/Test 系統的批准。該系統不對作業進行評分,也不記錄學生輸入 TEST 的次數;它只是協助學生和他們的教師。
BASIC 語言
第一個版本實現了以下陳述式類型,其部分運算子和關鍵字來自 FORTRAN II,部分來自 ALGOL 60。總體而言,該語言更接近 FORTRAN 模型,因為它通常每行程式碼只有一個陳述式,缺乏 ALGOL 用於分組程式碼的「區塊」(這些結構化程式設計結構是 ALGOL 發展的主要原因),並使用 GOTO 來控制程式流程。
它從 ALGOL 借鑒了 `FOR...TO...STEP` 風格的迴圈,取代了 FORTRAN 繁瑣的 `DO...CONTINUE` 陳述式。BASIC 還簡化了 `IF...THEN` 結構,允許像 `IF X=5 THEN 30` 這樣的簡單比較,而不是 FORTRAN 的 `IF (X-5) 20,20,30`。FORTRAN 風格的「計算型 IF」在後來的版本中以 `ON...GOTO` 指令重新引入。
變數名稱被限制為 A 到 Z、A0 到 A9、B0 到 B9、...、Z0 到 Z9,最多可有 286 個不同的變數。FORTRAN 將變數 I 到 N 設為整數、其餘設為浮點數的奇怪系統被移除,所有變數都被假定為浮點數,並可維度化至多 10 個元素。只有當陣列包含超過十個元素時,才需要 `DIM` 指令。陣列名稱僅限於 A 到 Z。
BASIC 陳述式列表
- `DEF`
- 定義單行函數
- `DIM`
- (dimension 的縮寫) 定義陣列的大小
- `END`
- 定義程式的結束
- `STOP`
- 在程式文本結束前停止程式
- `FOR / TO / STEP`
- 定義迴圈
- `NEXT`
- 標記迴圈的結束
- `GOSUB`
- 將控制權轉移到簡單的子程式
- `RETURN`
- 從簡單的子程式返回控制權
- `GOTO`
- 將控制權轉移到另一個陳述式
- `IF / THEN`
- 決策
- `LET / =`
- 將公式結果賦值給變數
- `PRINT`
- 輸出結果
- `DATA`
- 在程式中儲存靜態資料
- `READ`
- 輸入儲存在 DATA 陳述式中的資料
- `REM`
- 註解 ("REMark")
它還實現了浮點數變數和算術。
運算子列表
= <> < <= > >= + - * / ^ (指數)
函數列表
- `ABS`
- 絕對值
- `ATN`
- 反正切值 (結果以弧度為單位)
- `COS`
- 餘弦值 (參數以弧度為單位)
- `EXP`
- 指數值
- `INT`
- 整數值
- `LOG`
- 自然對數值
- `RND`
- 隨機值
- `SIN`
- 正弦值 (參數以弧度為單位)
- `SQR`
- 平方根值
- `TAN`
- 正切值 (參數以弧度為單位)
範例
早期版本的 BASIC 沒有讀寫外部檔案的能力。為了表示通常會從檔案中讀取的資料列表,BASIC 包含了 `DATA` 關鍵字,後面可以跟隨任意長的元素列表,僅受行長度限制。`DATA` 是非執行性的,如果遇到會被跳過。`READ` 指令會逐一消耗資料,並透過內部指標追蹤其在 `DATA` 元素完整集合中的位置。在第 3 版中,增加了 `RESTORE` 指令以將指標重置為程式中的第一個 `DATA` 指令。
在這個例子中,「前三個資料值分別被讀入 X、Y 和 Z。值 -1 被讀入 N。接下來的 11 個值,從 .1 到 .3,被讀入陣列 B 的 11 個元素中。」
<syntaxhighlight lang="basic"> 15 READ X, Y, Z 20 READ N 24 FOR I=0 TO 10 25 READ B(I) 26 NEXT I 40 DATA 4.2, 7.5, 25.1, -1, .1, .01, .001, .0001 45 DATA .2, .02, .002, .0002, .015, .025, .3, .03, .003 </syntaxhighlight>
與大多數後續的 BASIC 不同,達特茅斯 BASIC 從第三版開始,有一個矩陣關鍵字 `MAT`,它可以作為許多其他指令的前綴,用單一指令操作整個資料陣列。在這個來自 1968 年手冊的例子中,`MAT INPUT V` 用於輸入一系列變數。當使用者在一行中不輸入任何內容時,這個過程結束,並且元素的總數可以透過 `NUM` 偽變數存取。程式碼接著將矩陣中的所有單個元素相加並計算平均值。第三版還增加了縮排,這裡用來闡明迴圈結構。
<syntaxhighlight lang="basic"> 5 LET S = 0 10 MAT INPUT V 20 LET N = NUM 30 IF N = 0 THEN 99 40 FOR I = 1 TO N 45 LET S = S + V(I) 50 NEXT I 60 PRINT S/N 70 GO TO 5 99 END </syntaxhighlight>
註解
參考資料
引文
參考書目
外部連結
- 1965 年左右達特茅斯 BASIC 編譯器第 2 版原始碼列表 (2007 年存檔)
- 原始文件和軟體的掃描檔。
- Dartmouth BASIC Interpreter, RetroWiki.es
Category:Dartmouth College history Category:Programming languages created in 1964 Dartmouth BASIC Dartmouth BASIC Category:Time-sharing Category:BASIC programming language family Category:1964 software