mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	Merge pull request #2057 from steinwaywhw/master
Adding ATS language support by converting existing SublimeText syntax def
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							| @@ -555,6 +555,9 @@ | ||||
| [submodule "vendor/grammars/liquid.tmbundle"] | ||||
| 	path = vendor/grammars/liquid.tmbundle | ||||
| 	url = https://github.com/bastilian/validcode-textmate-bundles | ||||
| [submodule "vendor/grammars/ats.sublime"] | ||||
| 	path = vendor/grammars/ats.sublime | ||||
| 	url = https://github.com/steinwaywhw/ats-mode-sublimetext | ||||
| [submodule "vendor/grammars/Modelica"] | ||||
| 	path = vendor/grammars/Modelica | ||||
| 	url = https://github.com/BorisChumichev/modelicaSublimeTextPackage | ||||
|   | ||||
| @@ -130,6 +130,8 @@ vendor/grammars/assembly.tmbundle: | ||||
| vendor/grammars/atom-salt: | ||||
| - source.python.salt | ||||
| - source.yaml.salt | ||||
| vendor/grammars/ats.sublime: | ||||
| - source.ats | ||||
| vendor/grammars/autoitv3-tmbundle: | ||||
| - source.autoit.3 | ||||
| vendor/grammars/awk-sublime: | ||||
|   | ||||
| @@ -82,10 +82,9 @@ ATS: | ||||
|   - ats2 | ||||
|   extensions: | ||||
|   - .dats | ||||
|   - .atxt | ||||
|   - .hats | ||||
|   - .sats | ||||
|   tm_scope: source.ocaml | ||||
|   tm_scope: source.ats | ||||
|   ace_mode: ocaml | ||||
|  | ||||
| ActionScript: | ||||
|   | ||||
| @@ -1,215 +0,0 @@ | ||||
| %{ | ||||
| #include "./../ATEXT/atextfun.hats" | ||||
| %} | ||||
|  | ||||
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" | ||||
|    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> | ||||
| <html xmlns="http://www.w3.org/1999/xhtml"> | ||||
|  | ||||
| <head> | ||||
| <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> | ||||
| <title>EFFECTIVATS-DiningPhil2</title> | ||||
| #patscode_style() | ||||
| </head> | ||||
|  | ||||
| <body> | ||||
|  | ||||
| <h1> | ||||
| Effective ATS: Dining Philosophers | ||||
| </h1> | ||||
|  | ||||
| In this article, I present an implementation of a slight variant of the | ||||
| famous problem of 5-Dining-Philosophers by Dijkstra that makes simple but | ||||
| convincing use of linear types. | ||||
|  | ||||
| <h2> | ||||
| The Original Problem  | ||||
| </h2> | ||||
|  | ||||
| There are five philosophers sitting around a table and there are also 5 | ||||
| forks placed on the table such that each fork is located between the left | ||||
| hand of a philosopher and the right hand of another philosopher. Each | ||||
| philosopher does the following routine repeatedly: thinking and dining.  In | ||||
| order to dine, a philosopher needs to first acquire two forks: one located | ||||
| on his left-hand side and the other on his right-hand side. After | ||||
| finishing dining, a philosopher puts the two acquired forks onto the table: | ||||
| one on his left-hand side and the other on his right-hand side. | ||||
|  | ||||
| <h2> | ||||
| A Variant of the Original Problem  | ||||
| </h2> | ||||
|  | ||||
| The following twist is added to the original version: | ||||
|  | ||||
| <p> | ||||
|  | ||||
| After a fork is used, it becomes a "dirty" fork and needs to be put in a | ||||
| tray for dirty forks. There is a cleaner who cleans dirty forks and then | ||||
| puts them back on the table. | ||||
|  | ||||
| <h2> | ||||
| Channels for Communication | ||||
| </h2> | ||||
|  | ||||
| A channel is just a shared queue of fixed capacity. The following two | ||||
| functions are for inserting an element into and taking an element out of a | ||||
| given channel: | ||||
|  | ||||
| <pre | ||||
| class="patsyntax"> | ||||
| #pats2xhtml_sats("\ | ||||
| fun{a:vt0p} channel_insert (channel (a), a): void | ||||
| fun{a:vt0p} channel_takeout (chan: channel (a)): (a)  | ||||
| ")</pre> | ||||
|  | ||||
| If [channel_insert] is called on a channel that is full, then the caller is | ||||
| blocked until an element is taken out of the channel.  If [channel_takeout] | ||||
| is called on a channel that is empty, then the caller is blocked until an | ||||
| element is inserted into the channel. | ||||
|  | ||||
| <h2> | ||||
| A Channel for Each Fork | ||||
| </h2> | ||||
|  | ||||
| Forks are resources given a linear type. Each fork is initially stored in a | ||||
| channel, which can be obtained by calling the following function: | ||||
|  | ||||
| <pre | ||||
| class="patsyntax"> | ||||
| #pats2xhtml_sats("\ | ||||
| fun fork_changet (n: nphil): channel(fork) | ||||
| ")</pre> | ||||
|  | ||||
| where the type [nphil] is defined to be [natLt(5)] (for natural numbers | ||||
| less than 5). The channels for storing forks are chosen to be of capacity | ||||
| 2. The reason that channels of capacity 2 are chosen to store at most one | ||||
| element (in each of them) is to guarantee that these channels can never be | ||||
| full (so that there is no attempt made to send signals to awake callers | ||||
| supposedly being blocked due to channels being full). | ||||
|  | ||||
|  | ||||
| <h2> | ||||
| A Channel for the Fork Tray | ||||
| </h2> | ||||
|  | ||||
| A tray for storing "dirty" forks is also a channel, which can be obtained | ||||
| by calling the following function: | ||||
|  | ||||
| <pre | ||||
| class="patsyntax"> | ||||
| #pats2xhtml_sats("\ | ||||
| fun forktray_changet ((*void*)): channel(fork) | ||||
| ")</pre> | ||||
|  | ||||
| The capacity chosen for the channel is 6 (instead of 5) so that it can | ||||
| never become full (as there are only 5 forks in total). | ||||
|  | ||||
| <h2> | ||||
| Philosopher Loop | ||||
| </h2> | ||||
|  | ||||
| Each philosopher is implemented as a loop: | ||||
|  | ||||
| <pre | ||||
| class="patsyntax"> | ||||
| #pats2xhtml_dats('\ | ||||
| implement | ||||
| phil_loop (n) = let | ||||
| // | ||||
| val () = phil_think (n) | ||||
| // | ||||
| val nl = phil_left (n) // = n | ||||
| val nr = phil_right (n) // = (n+1) % 5 | ||||
| // | ||||
| val ch_lfork = fork_changet (nl) | ||||
| val ch_rfork = fork_changet (nr) | ||||
| // | ||||
| val lf = channel_takeout (ch_lfork) | ||||
| val () = println! ("phil_loop(", n, ") picks left fork") | ||||
| // | ||||
| val () = randsleep (2) // sleep up to 2 seconds | ||||
| // | ||||
| val rf = channel_takeout (ch_rfork) | ||||
| val () = println! ("phil_loop(", n, ") picks right fork") | ||||
| // | ||||
| val () = phil_dine (n, lf, rf) | ||||
| // | ||||
| val ch_forktray = forktray_changet () | ||||
| val () = channel_insert (ch_forktray, lf) // left fork to dirty tray | ||||
| val () = channel_insert (ch_forktray, rf) // right fork to dirty tray | ||||
| // | ||||
| in | ||||
|   phil_loop (n) | ||||
| end // end of [phil_loop] | ||||
| ')</pre> | ||||
|  | ||||
| It should be straighforward to follow the code for [phil_loop]. | ||||
|  | ||||
| <h2> | ||||
| Fork Cleaner Loop | ||||
| </h2> | ||||
|  | ||||
| A cleaner is implemented as a loop: | ||||
|  | ||||
| <pre | ||||
| class="patsyntax"> | ||||
| #pats2xhtml_dats('\ | ||||
| implement | ||||
| cleaner_loop () = let | ||||
| // | ||||
| val ch = forktray_changet () | ||||
| val f0 = channel_takeout (ch) // [f0] is dirty | ||||
| // | ||||
| val () = cleaner_wash (f0) // washes dirty [f0] | ||||
| val () = cleaner_return (f0) // puts back cleaned [f0] | ||||
| // | ||||
| in | ||||
|   cleaner_loop () | ||||
| end // end of [cleaner_loop] | ||||
| ')</pre> | ||||
|  | ||||
| The function [cleaner_return] first finds out the number of a given fork | ||||
| and then uses the number to locate the channel for storing the fork. Its | ||||
| actual implementation is given as follows: | ||||
|  | ||||
| <pre | ||||
| class="patsyntax"> | ||||
| #pats2xhtml_dats('\ | ||||
| implement | ||||
| cleaner_return (f) = | ||||
| { | ||||
|   val n = fork_get_num (f) | ||||
|   val ch = fork_changet (n) | ||||
|   val () = channel_insert (ch, f) | ||||
| } | ||||
| ')</pre> | ||||
|  | ||||
| It should now be straighforward to follow the code for [cleaner_loop]. | ||||
|  | ||||
| <h2> | ||||
| Testing | ||||
| </h2> | ||||
|  | ||||
| The entire code of this implementation is stored in the following files: | ||||
|  | ||||
| <pre> | ||||
| DiningPhil2.sats | ||||
| DiningPhil2.dats | ||||
| DiningPhil2_fork.dats | ||||
| DiningPhil2_thread.dats | ||||
| </pre> | ||||
|  | ||||
| There is also a Makefile available for compiling the ATS source code into | ||||
| an excutable for testing. One should be able to encounter a deadlock after | ||||
| running the simulation for a while. | ||||
|  | ||||
| <hr size="2"> | ||||
|  | ||||
| This article is written by <a href="http://www.cs.bu.edu/~hwxi/">Hongwei Xi</a>. | ||||
|  | ||||
| </body> | ||||
| </html> | ||||
|  | ||||
| %{ | ||||
| implement main () = fprint_filsub (stdout_ref, "main_atxt.txt") | ||||
| %} | ||||
							
								
								
									
										1
									
								
								vendor/grammars/ats.sublime
									
									
									
									
										vendored
									
									
										Submodule
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								vendor/grammars/ats.sublime
									
									
									
									
										vendored
									
									
										Submodule
									
								
							 Submodule vendor/grammars/ats.sublime added at 1e49e0b7e0
									
								
							
		Reference in New Issue
	
	Block a user